Rx способ выполнить что-то с точностью до c, пока условие не станет истинным или не истечет время ожидания - PullRequest
0 голосов
/ 06 марта 2020

У меня есть список имен заданий в таблице базы данных, который можно запустить, вызвав API с именем задания в качестве параметра. Каждая из этих работ занимает от 10 до 30 минут. Существует другой API, который можно вызывать через некоторый интервал (10 минут), чтобы проверить состояние завершения задания. Задание может быть запущено только после завершения предыдущего задания в списке / тайм-аута. То, что делают эти задания, здесь не имеет значения.

Я очень большой поклонник фреймворка Rx, но мало что о нем знаю.

В настоящее время я выбираю все имена заданий из db, затем перебираю их в каждый цикл я вызываю API триггера задания, чтобы запустить задание, а затем продолжаю вызывать API состояния задания с определенным интервалом, пока задание не будет завершено или не истекло время ожидания до начала следующего цикла задания.

foreach(string jobName in lstJobs)
{
 if(StartTheJob(jobName)) //if job successfully started
 {
    do{
        Task.Delay(10000);

    }
    While(GetJobCompletionStatus(jobName));
    // how to timeout this do/while loop
 }
}

Проблема в том, что если работа продолжается в течение нескольких часов, я не нахожу способ тайм-аута do while l oop и запуска следующей работы. Есть ли лучший способ сделать это с помощью Rx?

Ответы [ 2 ]

0 голосов
/ 07 марта 2020

Вот как это сделать с помощью Rx:

IObservable<string> query =
    from jobName in lstJobs.ToObservable()
    from started in Observable.Start(() => StartTheJob(jobName))
    where started
    from done in
        Observable.Amb(
            Observable.Timer(TimeSpan.FromMinutes(30.0)).Select(_ => true),
            Observable
                .Interval(TimeSpan.FromMinutes(10.0))
                .SelectMany(_ => Observable.Start(() => GetJobCompletionStatus(jobName)))
                .Where(s => s))
    select jobName;

Здесь логика c заключается в том, что вы выполняете каждое из заданий и вызываете StartTheJob. Если он успешен, то вы ожидаете done от (то есть .Amb(...)) 30-минутного .Timer(...) или вызовов на GetJobCompletionStatus, совершаемых каждые 10 минут, пока не будет возвращено true. Наконец, он возвращает jobName, чтобы вы могли увидеть, что было успешным. Когда наблюдаемое завершится, вы можете сравнить его с исходным списком, чтобы увидеть, были ли какие-либо неудачные.

0 голосов
/ 06 марта 2020

Используйте CancellationToken:

foreach(string jobName in lstJobs)
{
 if(StartTheJob(jobName)) //if job successfully started
 {
    do{
        Task.Delay(10000);

    }
    While(!ct.IsCancellationRequested);
 }
}

Вы можете создать CancellationToken, используя CancellationTokenSource:

var cts = new CancellationTokenSource(timeout);
var ct = cts.Token;
...