Как получить список всех заданий 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.