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

Creating an async method which throws an exception after a specified amount of time unless a certain condition is met outside of that function

我目前正在编写一个 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.

中的代码的建议

提前致谢:)

编辑:在示例中,我向 start_task_and_throw_timeout 添加了一个 std::function 参数,因此它可重复用于所有类似的功能

我认为模块 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. The documentation for the module lives here: https://ruby-doc.org/stdlib-2.5.1/libdoc/timeout/rdoc/Timeout.html。请注意,您不仅可以自定义超时时间,还可以自定义错误 class 和消息,因此不同的作业可能会有不同类型的错误。