TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #2612 2.73K
День 2162. #ЗаметкиНаПолях
Планировка Фоновых Задач с Помощью Quartz. Окончание

Начало

Планирование повторяющихся заданий
Для повторяющихся фоновых заданий можно использовать расписания cron:
public record RecurringReminder(
string UserId,
string Message,
string CronExpression
);

app.MapPost("/api/recurring/schedule", async (
ISchedulerFactory schFactory,
RecurringReminder rem) =>
{
var scheduler = await schFactory.GetScheduler();
var jobData = new JobDataMap
{
{ "userId", rem.UserId },
{ "message", rem.Message }
};

var group = "recurring-reminders";

var job = JobBuilder.Create<EmailJob>()
.WithIdentity(
$"recurring-{Guid.NewGuid()}", group)
.SetJobData(jobData)
.Build();

var trigger = TriggerBuilder.Create()
.WithIdentity(
$"rectrigger-{Guid.NewGuid()}", group)
.WithCronSchedule(rem.CronExpression)
.Build();

await scheduler.ScheduleJob(job, trigger);

return Results.Ok(new {
scheduled = true,
cron = rem.CronExpression });
})
.WithName("RecurringReminder")
.WithOpenApi();

Триггеры Cron более эффективны, чем простые. Они позволяют определять сложные расписания, например «каждый будний день в 10 утра»:
POST /api/recurring/schedule
{
"userId": "user69",
"message": "Daily",
"cronExpression": "0 0 10 ? * MON-FRI"
}


Настройка хранения заданий
По умолчанию Quartz использует хранилище в памяти, т.е. задания теряются при перезапуске приложения. Для постоянного хранения поддерживается несколько провайдеров БД. Вот как настроить постоянное хранилище с надлежащей изоляцией схемы:
builder.Services.AddQuartz(opts =>
{
opts.AddJob<EmailJob>(c => c
.StoreDurably()
.WithIdentity(EmailJob.Name));

opts.UsePersistentStore(o =>
{
o.UsePostgres(cfg =>
{
cfg.ConnectionString = "…";
cfg.TablePrefix = "scheduler.qrtz_";
},
dataSourceName: "reminders"); // Имя БД

o.UseNewtonsoftJsonSerializer();
o.UseProperties = true;
});
});

Замечания:
- TablePrefix помогает организовать таблицы Quartz - в данном случае, помещая их в отдельную схему scheduler;
- Нужно будет запустить соответствующие скрипты БД для создания этих таблиц. Каждый поставщик БД имеет свои скрипты настройки.

Долгосрочные Задания
Мы настроили EmailJob с StoreDurably. Это позволяет определить задание 1 раз и повторно использовать его с разными триггерами:
public async Task ScheduleReminder(
string userId, string msg, DateTime dt)
{
var scheduler = await schFactory.GetScheduler();

// Извлекаем задание по его имени
var jobKey = new JobKey(EmailJob.Name);

var trigger = TriggerBuilder.Create()
// Используем задание по ссылке
.ForJob(jobKey)
.WithIdentity($"trigger-{Guid.NewGuid()}")
.UsingJobData("userId", userId)
.UsingJobData("message", msg)
.StartAt(dt)
.Build();
// Передаём только триггер
await scheduler.ScheduleJob(trigger);
}

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

Источник: https://www.milanjovanovic.tech/blog/scheduling-background-jobs-with-quartz-in-dotnet-advanced-concepts
  • 👍 9
More from @netdeveloperdiary
  1. Oct 5, 2026🦈 Открытое собеседование на Middle C# | 6 октября, 19:00 МСК Приглашаем на открытое собес…
  2. Oct 5, 2026День 2805. #ЧтоНовенького #NET11 Аргументы в Выражениях Коллекций в C#15 В C#15 реализован…
  3. Oct 4, 2026День 2804. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
  4. Oct 3, 2026Post #3360
  5. Oct 3, 2026День 2803. #Оффтоп Чем Заняться, Пока Работают Агенты? У VS Code Есть Ответ Сейчас большую…
  6. Oct 2, 2026День 2802. #Карьера #Юмор Секреты Программирования, Известные Только Легендам Ещё один пос…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →