Создание метода asyn c, который генерирует исключение по прошествии определенного времени, если не выполняется определенное условие за пределами этой функции. - PullRequest
0 голосов
/ 28 мая 2020

В настоящее время я работаю над сценарием Ruby, который должен выполнять различные задачи на довольно длинном списке хостов. Я использую гем net -s sh для связи с этими хостами. Дело в том, что, похоже, существуют некоторые условия, при которых время ожидания net -s sh истекает без создания исключения. Как известно, скрипт только один раз смог завершить sh прогон. В большинстве случаев скрипты просто зависают в какой-то момент, даже не вызывая исключения или ничего не делая.

Я думал о запуске всех задач, которые могут истекать по таймауту, в разных потоках, передавая им указатель на некоторую переменную, которую они могут изменить после успешного завершения задачи, а затем проверять эту переменную в течение заданного количества времени. Если к тому времени задача не будет завершена, вызовите исключение в основном потоке, которое я могу где-то перехватить.

Я впервые пишу что-то в Ruby. Чтобы наглядно продемонстрировать, чего я хочу достичь sh, вот что я бы сделал в 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', исключение составляет брошен в основной поток. Если задача завершается вовремя, все идет гладко.

Однако мне нужно написать свою программу на языке сценариев c Dynami, который может работать где угодно и не требует компиляции. Я был бы очень рад любому совету о том, как я могу написать что-то вроде приведенного выше кода в Ruby.

Заранее большое спасибо :)

edit: в этом примере я добавил std :: function для start_task_and_throw_timeout, чтобы его можно было повторно использовать для всех подобных функций

1 Ответ

1 голос
/ 28 мая 2020

Думаю, в модуле 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. Обратите внимание, что вы можете настроить не только тайм-аут, но также класс ошибки и сообщение, поэтому разные задания могут иметь разные типы ошибок.

...