← Назад к вопросам

Приведи пример сценария для использования планировщика задач

2.0 Middle🔥 202 комментариев

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Пример сценария для использования планировщика задач в C# Backend

В современных backend-приложениях планировщик задач (Task Scheduler) является критически важным компонентом для автоматизации повторяющихся операций, фоновой обработки и поддержания целостности системы. Рассмотрим реальный сценарий из e-commerce платформы — систему автоматической архивации заказов и очистки устаревших данных.

Контекст сценария

E-commerce платформа ежедневно обрабатывает тысячи заказов. Со временем база данных разрастается, что приводит к:

  • Ухудшению производительности запросов
  • Увеличению затрат на хранение
  • Замедлению резервного копирования

Бизнес-требования:

  1. Автоматически архивировать заказы старше 2 лет в холодное хранилище
  2. Удалять корзины покупок, неактивные более 30 дней
  3. Очищать логи ошибок старше 90 дней
  4. Отправлять еженедельный отчет администратору
  5. Выполнять операции в непиковые часы (ночью)

Техническая реализация на C# с Quartz.NET

using Quartz;
using Quartz.Impl;

public class OrderArchivingJob : IJob
{
    private readonly IOrderRepository _orderRepository;
    private readonly ILogger<OrderArchivingJob> _logger;
    
    public OrderArchivingJob(IOrderRepository orderRepository, 
                             ILogger<OrderArchivingJob> logger)
    {
        _orderRepository = orderRepository;
        _logger = logger;
    }
    
    public async Task Execute(IJobExecutionContext context)
    {
        try
        {
            _logger.LogInformation("Начало архивации старых заказов");
            
            // 1. Находим заказы старше 2 лет
            var cutoffDate = DateTime.UtcNow.AddYears(-2);
            var oldOrders = await _orderRepository.GetOrdersOlderThan(cutoffDate);
            
            // 2. Архивируем в холодное хранилище
            await ArchiveToColdStorage(oldOrders);
            
            // 3. Удаляем из основной БД (или помечаем как архивные)
            await _orderRepository.MarkAsArchived(oldOrders.Select(o => o.Id));
            
            // 4. Логируем результаты
            _logger.LogInformation(
                "Архивировано {Count} заказов старше {Date}", 
                oldOrders.Count, 
                cutoffDate.ToString("yyyy-MM-dd")
            );
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Ошибка при архивации заказов");
            throw new JobExecutionException(ex, false);
        }
    }
    
    private async Task ArchiveToColdStorage(List<Order> orders)
    {
        // Реализация архивации в Azure Blob Storage / AWS S3 / etc.
        foreach (var order in orders)
        {
            var serialized = JsonSerializer.Serialize(order);
            await _coldStorage.SaveAsync($"orders/archived/{order.Id}.json", serialized);
        }
    }
}

Конфигурация планировщика

public class SchedulerSetup
{
    public static async Task<IScheduler> ConfigureScheduler(IServiceProvider services)
    {
        // Фабрика планировщика
        var schedulerFactory = new StdSchedulerFactory();
        var scheduler = await schedulerFactory.GetScheduler();
        scheduler.JobFactory = new CustomJobFactory(services);
        
        // Задача архивации заказов (ежедневно в 2:00)
        var archiveJob = JobBuilder.Create<OrderArchivingJob>()
            .WithIdentity("orderArchiveJob", "maintenance")
            .Build();
            
        var archiveTrigger = TriggerBuilder.Create()
            .WithIdentity("orderArchiveTrigger", "maintenance")
            .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(2, 0))
            .Build();
        
        // Задача очистки корзин (каждые 6 часов)
        var cleanupJob = JobBuilder.Create<CartCleanupJob>()
            .WithIdentity("cartCleanupJob", "maintenance")
            .Build();
            
        var cleanupTrigger = TriggerBuilder.Create()
            .WithIdentity("cartCleanupTrigger", "maintenance")
            .WithSimpleSchedule(x => x
                .WithIntervalInHours(6)
                .RepeatForever())
            .Build();
        
        // Регистрация задач
        await scheduler.ScheduleJob(archiveJob, archiveTrigger);
        await scheduler.ScheduleJob(cleanupJob, cleanupTrigger);
        
        return scheduler;
    }
}

Ключевые преимущества использования планировщика в данном сценарии

1. Автоматизация рутинных операций:

  • Исключение человеческого фактора
  • Гарантированное выполнение по расписанию
  • Централизованное управление задачами

2. Контроль нагрузки на систему:

  • Выполнение ресурсоемких задач в непиковое время
  • Возможность паузы/возобновления задач
  • Балансировка нагрузки через кластеризацию Quartz

3. Надежность и отслеживаемость:

  • Встроенные механизмы повторения при сбоях
  • Детальное логирование выполнения
  • История выполнения задач

4. Гибкость конфигурации:

  • Различные типы триггеров (cron, simple, calendar)
  • Возможность динамического добавления/удаления задач
  • Конфигурация через код или XML

Расширение сценария

В реальном проекте можно добавить:

// Мониторинг и алертинг
public class MonitoringJob : IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        // Проверка здоровья системы
        // Проверка свободного места на диске
        // Проверка времени ответа БД
        // Отправка алертов при проблемах
    }
}

// Отчетность
public class ReportingJob : IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        // Генерация еженедельных отчетов
        // Агрегация статистики
        // Экспорт данных для BI-систем
    }
}

Альтернативные решения

Для данного сценария также подходят:

  • Hangfire — для более простой настройки и веб-интерфейса
  • BackgroundService в ASP.NET Core — для простых периодических задач
  • Azure Functions / AWS Lambda с Timer Trigger — в serverless-архитектуре

Заключение

Представленный сценарий демонстрирует, как планировщик задач решает комплексные проблемы обслуживания production-системы. Правильная реализация обеспечивает:

  • Снижение операционных расходов
  • Улучшение производительности приложения
  • Автоматизацию бизнес-процессов
  • Проактивное обслуживание системы

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

Приведи пример сценария для использования планировщика задач | PrepBro