创建一个异步方法,该方法在指定的时间量后引发异常,除非在该函数之外满足特定条件



我目前正在开发一个Ruby脚本,该脚本应该在很长的主机列表中执行不同的任务。我正在使用 net-ssh gem 与这些主机连接。问题是,似乎存在一些 net-ssh 超时而不会引发异常的情况。据了解,该脚本只有一次能够完成运行。大多数情况下,脚本只是在某个时候挂起,而不会引发异常或执行任何操作。

我想过在不同的线程中运行所有可能超时的任务,向它们传递一个指针,指向任务成功完成时他们可以更改的某个变量,然后在给定的时间内检查该变量。如果任务到那时还没有完成,请在主线程中抛出一个异常,我可以在某处捕获该异常。

这是我第一次用 Ruby 写东西。为了清楚地展示我想要完成的目标,这是我在C++中要做的事情:

void perform_long_running_task(bool* finished);
void start_task_and_throw_on_timeout(int secs, std::function<void(bool*)> func);
int seconds_to_wait {5};
int seconds_task_takes{6};

int main() {
start_task_and_throw_on_timeout(seconds_to_wait, &perform_long_running_task);
// do other stuff
return 0;
}
void perform_long_running_task(bool* finished){
// Do something that may possible timeout..
std::this_thread::sleep_for(std::chrono::seconds(seconds_task_takes));
// Finished..
*finished = true;
}
void start_task_and_throw_on_timeout(int secs, std::function<void(bool*)> func){
bool finished {false};
std::thread task(func, &finished);
while (secs > 0){
std::this_thread::sleep_for(std::chrono::seconds(1));
secs--;
if (finished){
task.join();
return;
}
}
throw std::exception();
}

在这里,当"seconds_task_takes"大于"seconds_to_wait"时,主线程中会抛出异常。如果任务及时完成,一切都会顺利进行。

但是,我需要用动态脚本语言编写我的软件,该语言可以在任何地方运行,并且不需要编译。我会非常高兴任何关于如何在 Ruby 中编写类似上述代码的建议。

提前非常感谢:)

编辑:在示例中,我添加了一个 std::function 参数到start_task_and_throw_timeout以便它可以重用于所有类似的函数

我认为模块timeout拥有您需要做的一切。它允许您运行块一段时间,如果速度不够快,则引发异常。

下面是一个代码示例:

require "timeout"
def run(name)
puts "Running the job #{name}"
sleep(10)
end

begin
Timeout::timeout(5) { run("hard") }
rescue Timeout::Error
puts "Failed!"
end

你可以在这里玩它:https://repl.it/repls/CraftyUnluckyCore。该模块的文档位于此处:https://ruby-doc.org/stdlib-2.5.1/libdoc/timeout/rdoc/Timeout.html。请注意,您不仅可以自定义超时,还可以自定义错误类和消息,因此不同的作业可能会有不同类型的错误。

最新更新