Что такое библиотека Quartz.NET?

Ответ

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, не ошибёшься.