Как выполнить новое задание при успешном или неудачном выполнении задания Hangfire?

Я работаю над службой RESTful веб-API, которая по запросу должна выполнять задачу. Мы используем Hangfire для выполнения этой задачи как задания и в случае сбоя попытаемся повторить задание до 10 раз.

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

Однако я не могу понять, как это сделать. Я создал следующий атрибут JobFilterAttribute:

public class HandleEventsAttribute : JobFilterAttribute, IElectStateFilter
{
    public IBackgroundJobClient BackgroundJobClient { get; set; }

    public void OnStateElection(ElectStateContext context)
    {
        var failedState = context.CandidateState as FailedState;
        if (failedState != null)
        {
            BackgroundJobClient.Enqueue<MyJobClass>(x => x.RunJob());
        }
    }
}

Единственная проблема, с которой я столкнулся, — это внедрение IBackgroundJobClient в этот атрибут. Я не могу передать его как свойство атрибуту (я получаю сообщение об ошибке «Не удается получить доступ к нестатическому полю backgroundJobClient в статическом контексте»). Мы используем autofac для внедрения зависимостей, и я пытался выяснить, как использовать внедрение свойств, но я в недоумении. Все это приводит меня к мысли, что я, возможно, на ложном пути.

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

Спасибо за помощь. Дайте мне знать, если есть какие-либо дополнительные сведения, которые я могу предоставить.


person Anthony Frasso    schedule 14.11.2015    source источник


Ответы (2)


Hangfire может выстраивать цепочки исполнения. Если вы хотите запланировать следующее задание после успешного выполнения первого, вам нужно использовать ContinueWith(string parentId, Expression<Action> methodCall, JobContinuationOptions options); с JobContinuationOptions.OnlyOnSucceededState, чтобы запустить его только после успеха.

Но вы можете создать расширение HangFire, такое как JobExecutor, и запускать задачи внутри него, чтобы получить больше возможностей.

Что-то подобное:

public static JobResult<T> Enqueue<T>(Expression<Action> a, string name)
{
    var exprInfo = GetExpressionInfo(a);

    Guid jGuid = Guid.NewGuid();

    var jobId = BackgroundJob.Enqueue(() => JobExecutor.Execute(jGuid, exprInfo.Method.DeclaringType.AssemblyQualifiedName, exprInfo.Method.Name, exprInfo.Parameters, exprInfo.ParameterTypes));            

    JobResult<T> result = new JobResult<T>(jobId, name, jGuid,  0, default(T));
    JobRepository.WriteJobState(new JobResult<T>(jobId, name, jGuid, 0, default(T)));

    return result;
}

Более подробную информацию вы можете найти здесь: https://indexoutofrange.com/Don%27t-do-it-now!-Part-5.-Hangfire-job-continuation,-ContinueWith/

person Anton Anpilogov    schedule 04.07.2017

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

Когда я ставлю задачи в очередь, я использую статический Hangfire.BackgroundJob.Enqueue, который должен работать без ссылки на экземпляр JobClient.

Стив

person Steve    schedule 12.12.2015