Ответ
Quartz.NET — это полнофункциональная, open-source библиотека для планирования заданий (job scheduling) в приложениях .NET. Она позволяет выполнять задачи (jobs) по сложному расписанию, например, в определенное время, с периодичностью или по Cron-выражениям.
Ключевые компоненты и возможности:
- Scheduler (Планировщик): Центральный компонент для управления выполнением заданий.
- Job (Задание): Логическая задача, которую нужно выполнить. Реализует интерфейс
IJob. - Trigger (Триггер): Определяет когда должно выполняться задание (например, "каждые 30 секунд", "в 2:00 каждый день").
- JobStore (Хранилище): Поддерживает персистентность (сохранение заданий и триггеров в БД, например, SQL Server, PostgreSQL), что критично для кластерных конфигураций и перезапусков приложения.
- Кластеризация: Поддержка отказоустойчивых кластеров, где выполнение задания гарантированно происходит только на одном узле.
Типичный сценарий использования — фоновый сервис для отправки отчетов:
// 1. Определяем задание
public class DailyReportJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
var reportData = await _reportService.GenerateDailyReportAsync();
await _emailService.SendReportAsync(reportData);
// Данные можно передавать через JobDataMap в context.JobDetail
}
}
// 2. Настраиваем и запускаем планировщик (обычно в Program.cs или Startup)
public static async Task ScheduleJobs(IServiceProvider serviceProvider)
{
var schedulerFactory = new StdSchedulerFactory();
var scheduler = await schedulerFactory.GetScheduler();
scheduler.JobFactory = new MyJobFactory(serviceProvider); // Для DI
await scheduler.Start();
// 3. Создаем задание и триггер
var job = JobBuilder.Create<DailyReportJob>()
.WithIdentity("dailyReport", "reports")
.Build();
// Триггер, который срабатывает каждый день в 8:00 утра
var trigger = TriggerBuilder.Create()
.WithIdentity("dailyTrigger", "reports")
.StartNow()
.WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(8, 0))
.Build();
// 4. Планируем выполнение
await scheduler.ScheduleJob(job, trigger);
}
Почему выбирают Quartz.NET? Для сложных расписаний, требующих персистентности, кластеризации и надежности. Для простых периодических задач в ASP.NET Core можно рассмотреть BackgroundService или IHostedService.
Ответ 18+ 🔞
А, Quartz.NET! Ну, это такая библиотека, если тебе нужно, чтобы что-то в твоём приложении делалось не просто когда попало, а по чёткому, ебучему расписанию. Типа, "отправляй отчёт каждый день в 8 утра" или "чисти кэш каждые 30 секунд, как часы". Открытый исходник, всё дела.
Что там внутри, из чего это собрано, блядь:
- Планировщик (Scheduler): Это главный мозг, царь и бог. Он всем рулит, решает, когда какую работу запускать. Без него нихуя не работает.
- Задание (Job): Это и есть сама работа, которую надо сделать. Просто пишешь класс, который реализует
IJob. Всё, логика там. - Триггер (Trigger): А вот это — самое интересное. Это такая сущность, которая планировщику в уши дует: "Эй, падла, запускай это задание не абы как, а в два часа ночи, в последний понедельник месяца, когда луна в Водолее!". Можно по Cron-выражениям, можно по интервалам — полная свобода, блядь.
- Хранилище (JobStore): Вот это — критически важная хуйня, если ты не идиот. Оно всё твоё расписание, все задания и триггеры — сохраняет в базу данных. SQL Server, PostgreSQL, да кто угодно. Зачем? А представь, твоё приложение упало, перезапустилось. Без этого хранилища все твои запланированные задачи — нахуй сгорели, забылись. А с ним — всё как было, восстановилось и работает. Для кластеров — вообще святое.
- Кластеризация: Говоря по-русски, можно запустить несколько экземпляров твоего приложения, и они будут как один организм. Задание гарантированно выполнится только на одной из этих нод, а не на всех сразу. Чтобы не было пиздеца, когда одна и та же рассылка улетает пять раз.
Ну, например, тебе надо слать ежедневный отчёт. Как это выглядит в коде:
// 1. Вот твоё задание — что делать?
public class DailyReportJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
// Сгенерировал отчёт
var reportData = await _reportService.GenerateDailyReportAsync();
// И отправил нахуй, то есть на почту
await _emailService.SendReportAsync(reportData);
// Данные для работы можно в контекст пихнуть, через JobDataMap
}
}
// 2. Настраиваем и запускаем эту машину (обычно при старте приложения)
public static async Task ScheduleJobs(IServiceProvider serviceProvider)
{
// Берём фабрику, делаем планировщик
var schedulerFactory = new StdSchedulerFactory();
var scheduler = await schedulerFactory.GetScheduler();
// Подключаем свою фабрику заданий, чтобы Dependency Injection работал
scheduler.JobFactory = new MyJobFactory(serviceProvider);
// Запускаем движок!
await scheduler.Start();
// 3. Лепим само задание
var job = JobBuilder.Create<DailyReportJob>()
.WithIdentity("dailyReport", "reports") // Даём имя и группу, чтобы потом найти
.Build();
// 4. А теперь — магия триггера! Каждый день в 8:00.
var trigger = TriggerBuilder.Create()
.WithIdentity("dailyTrigger", "reports")
.StartNow()
.WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(8, 0))
.Build();
// 5. Сводим задание и триггер вместе и отдаём планировщику
await scheduler.ScheduleJob(job, trigger);
}
Так когда эту банду использовать? Да когда у тебя расписание сложнее, чем "раз в минуту", и когда надёжность на первом месте. Если приложение упало — задания не должны потеряться. Если нод много — они не должны друг другу мешать. Для простых цикличных задач в ASP.NET Core есть BackgroundService, но это, блядь, как сравнивать велосипед и грузовик. Для серьёзных объёмов и сложных маршрутов — бери Quartz, не ошибёшься.