Как получить список всех заданий Hangfire, используя JobStorage в C#?

Я использую Hangfire BackgroundJob создать фоновое задание в C# с помощью приведенного ниже кода.

var options = new BackgroundJobServerOptions
        {
            ServerName = "Test Server",
            SchedulePollingInterval = TimeSpan.FromSeconds(30),
            Queues = new[] { "critical", "default", "low" },
            Activator = new AutofacJobActivator(container),
        };
        var jobStorage = new MongoStorage("mongodb://localhost:*****", "TestDB", new MongoStorageOptions()
        {
            QueuePollInterval = TimeSpan.FromSeconds(30)                
        });
        var _Server = new BackgroundJobServer(options, jobStorage);

Он создает объект Jobserver, и после этого я создаю расписание, повторяющиеся задания, как показано ниже.

var InitJob = BackgroundJob.Schedule<TestInitializationJob>(job => job.Execute(), TimeSpan.FromSeconds(5));
        var secondJob = BackgroundJob.ContinueWith<Test_SecondJob>(InitJob, job => job.Execute());
        BackgroundJob.ContinueWith<Third_Job>(secondJob, job => job.Execute());
        RecurringJob.AddOrUpdate<RecurringJobInit>("test-recurring-job", job => job.Execute(), Cron.MinuteInterval(1));

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

var monitoringApi = JobStorage.Current.GetMonitoringApi();
                    var queues = monitoringApi.Queues();// BUT this is not returning all queues and all jobs
                    foreach (QueueWithTopEnqueuedJobsDto queue in queues)
                    {
                        var jobList  = monitoringApi.EnqueuedJobs(queue.Name, 0, 100);
                        foreach (var item in jobList)
                        {
                            BackgroundJob.Delete(item.Key);
                        }
                    }

Но приведенный выше код для получения всех заданий и всех очередей не работает. Оно всегда возвращается "default" очереди и не возвращаются все вакансии.

У кого-нибудь может быть идея получить все рабочие места, используя Hangfire JobStorage и останавливает эту работу, когда приложение остановлено?

Любая помощь будет высоко оценен!

Спасибо

1 ответ

Настройка одного сервера

Чтобы получить все повторяющиеся задания, вы можете использовать хранилище заданий (например, через статический экземпляр или DI):

      using (var connection = JobStorage.Current.GetConnection())
{
  var recurringJobs = connection.GetRecurringJobs();
  foreach (var recurringJob in recurringJobs)
  {
    if (NonRemovableJobs.ContainsKey(recurringJob.Id)) continue;
    logger.LogWarning($"Removing job with id [{recurringJob.Id}]");
    jobManager.RemoveIfExists(recurringJob.Id);
  }
}

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

Настройка нескольких серверов

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

Чтобы предотвратить это, я использовал следующий обходной путь, который загружает столбец «Ключ» из таблицы «Хэш». Он имеет формат «повторяющиеся задания: {YourJobIdentifier}». Затем идентификатор задания используется для удаления задания, если это необходимо:

      var queue = 'MyInstanceQueue'; // probably using queues in a multi server setup
var recurringJobsRaw = await dbContext.HangfireHashes.FromSqlInterpolated($"SELECT [Key] FROM [Hangfire].[Hash] where Field='Queue' AND Value='{queue}'").ToListAsync();
var recJobIds = recurringJobsRaw.Select(s => s.Key.Split(":").Last());
foreach (var id in recJobIds)
{
  if (NonRemovableJobs.ContainsKey(id)) continue;
  logger.LogWarning($"Removing job with id [{id}]");
  jobManager.RemoveIfExists(id);
}

PS: Чтобы он работал с EF Core, я использовал объект Keyless для таблицы Hangfire.Hash.

Другие вопросы по тегам