Как предотвратить повторение выполнения задания после перезапуска IIS? - PullRequest
1 голос
/ 05 ноября 2019

После того как мы установили Hangfire (v1.7.7) на всегда запускать , все повторяющиеся задания выполняются сразу после перезапуска IIS или перезапуска пула. Это нежелательное поведение, потому что у нас запланированы задания, которые запускаются раз в месяц или раз в неделю, и при каждом развертывании они запускаются.

Нам не удалось найти свойство конфигурации в документации или на форумах, чтобы предотвратить это поведение имы все еще анализируем репозиторий, пытаясь найти подсказку.

Мы нашли эту проблему и это обсуждение касалось нашей проблемы.

Помимо приведенной выше ссылки, которая представляет собой точную конфигурацию, которую мы сделали для того, чтобы Hangfire всегда работал, это наша текущая конфигурация:

private BackgroundJobServer _backgroundJobServer;
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
    Authorization = new[] { new HangfireRestrictiveAuthorizationFilter() },
    StatsPollingInterval = UM_MINUTO_EM_MILISEGUNDOS * 10
});

GlobalConfiguration.Configuration.UseSqlServerStorage("Implanta", new SqlServerStorageOptions 
{ 
    CommandBatchMaxTimeout = TimeSpan.FromMinutes(5), 
    SchemaName = "HangFireSiscaf",
    SlidingInvisibilityTimeout = null
});

_backgroundJobServer = new BackgroundJobServer(new BackgroundJobServerOptions()
{
    Queues = new[] { "siscaf" },
    ServerName = "SISCAF.NET",
    WorkerCount = 5
});

И вот как мы обычно планируем наши повторяющиеся работы (параимена методов и строки записываются в pt-BR):

RecurringJob.AddOrUpdate<ColetaMensalCFATask>(
    ColetaMensalCFATask.Key,
    x => x.ExecuteTask(),
    Cron.Monthly(diaAgendamentoMensalColetaCFA, timeSpanHoraAgendamentoMensalColetaCFA.Minutes),
    TimeZoneInfo.Local,
    "siscaf");

ОБНОВЛЕНИЕ 1: Мы смогли воспроизвести желаемое поведение, удалив историю выполнения задания и добавив каждое задание в виденовый. Хотя это не удачное решение.

1 Ответ

1 голос
/ 05 ноября 2019

Всякий раз, когда вам нужно изменить поведение внутри Hangfire, вы должны написать JobFilter .

Этот класс может реализовывать различные интерфейсы, но в вашем случае вы, вероятно, могли бы реализовать IClientFilterи отметьте OnCreating(), если задание должно быть создано, или внедрите IElectStateFilter и отметьте OnStateElection(), если задание должно быть поставлено в очередь.

Помните, что уже есть куча других фильтров задания и чтоони выполняются в определенном порядке, заданном целочисленным значением в свойстве Order. Чтобы убедиться, что ваш фильтр будет одним из последних, установите для этого значение, возможно, значение int.MaxValue.

Чтобы применить этот фильтр задания к своей работе, вы можете либо добавить атрибут к методу или классу, либо, если он долженбыть выполненным для каждой работы, которую вы можете добавить в глобальный список с помощью GlobalJobFilters.Filters.Add() при запуске.

Если вы находитесь в одном из методов фильтрации, у каждого из них есть свойство context, которое имеетдоступ к API мониторинга через свойство Storage:

var monitor = context.Storage.GetMonitoringApi();
var jobDetails = monitor.JobDetails(context.BackgroundJob.Id);

foreach (var kvp in jobDetails.Properties)
{
    Trace.WriteLine($"{kvp.Key => kvp.Value}");
}

foreach (var entry in jobDetails.History.OrderBy(e => e.CreatedAt))
{
    Trace.WriteLine($"{entry.StateName} ({entry.CreatedAt}): {Reason}");

    foreach (var kvp in entry.Data)
    {
        Trace.WriteLine($"   {kvp.Key} => {kvp.Value}");
    }
}

В настоящее время я не могу проверить, что они содержат в случае вновь созданного повторяющегося задания, но если вы посмотрите на него с помощью отладчикаВы должны найти некоторую информацию о повторяющейся работе. Один простой способ проверить это - взглянуть на панель управления Hangfire. Если вы откроете страницу сведений о задании и найдете что-нибудь, связанное с повторяющимся заданием, чем это доступно через API мониторинга, все веб-страницы Hangfire используют этот API для получения своего контента.

Просто копните немного глубже инашел точки для извлечения всей информации из повторяющегося задания по заданному идентификатору задания:

var monitor = context.Storage.GetMonitoringApi();
var jobDetails = monitor.JobDetails(context.BackgroundJob.Id);

if(jobDetails.Properties.TryGetValue("RecurringJobId", out string recurringId))
{
    var values = context.Connection.GetAllEntriesFromHash($"recurring-job:{recurringId}");

    foreach (var kvp in values)
    {
        Trace.WriteLine($"{kvp.Key} => {kvp.Value}");
    }
}

Кроме того, состояние Enqueued повторяющегося задания всегда имеет в качестве причины текст Triggered by recurring job scheduler, который можно использовать какфильтр как это:

    public void OnStateElection(ElectStateContext context)
    {
        switch (context.CandidateState)
        {
            case EnqueuedState enqueued when enqueued.Reason == "Triggered by recurring job scheduler":
                Trace.WriteLine($"Was triggered by job scheduler.");

                // Skip all jobs of job scheduler
                context.CandidateState = new SucceededState(null, 0, 0);
                break;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...