Что такое Hangfire и зачем она нужна?
Hangfire — это мощная и популярная библиотека для C# (.NET), предназначенная для выполнения фоновых задач (background jobs). В современной веб-разработке часто возникает необходимость выполнять операции, которые не должны блокировать основной поток выполнения приложения. Например: отправка email-уведомлений, генерация отчетов, обработка загруженных файлов, синхронизация данных с внешними API, очистка устаревших записей в базе данных и многое другое.
Hangfire предоставляет простой, но гибкий способ запускать такие задачи. Ключевые возможности библиотеки:
- Выполнение задач в фоне: Задачи выполняются асинхронно, не блокируя ответ пользователю.
- Планирование: Можно запускать задачи по расписанию (cron-выражения) или с задержкой.
- Надежность: Hangfire сохраняет информацию о задачах в постоянном хранилище (база данных). Даже если приложение перезапустится, незавершенные задачи будут выполнены.
- Мониторинг: Встроенный веб-интерфейс (Dashboard) позволяет отслеживать статус задач, просматривать логи, повторно запускать упавшие задачи.
- Повторные попытки: Если задача завершилась ошибкой, Hangfire автоматически попытается выполнить ее снова (с настраиваемой политикой повторных попыток).
- Интеграция с DI: Легко интегрируется с контейнерами внедрения зависимостей (Dependency Injection) в ASP.NET Core.
Hangfire поддерживает различные хранилища: SQL Server, PostgreSQL, Redis, MongoDB и другие. Это делает ее подходящей для проектов любого масштаба — от небольших сайтов до высоконагруженных корпоративных систем.
Установка
Hangfire устанавливается через NuGet Package Manager. В отличие от Python, где используется pip install, в .NET экосистеме используется dotnet add package или менеджер пакетов Visual Studio.
Для установки базового пакета Hangfire выполните команду в терминале (в корневой папке вашего проекта):
dotnet add package Hangfire
Эта команда установит ядро Hangfire и зависимости для хранения задач в памяти (InMemory). Для продакшн-среды вам понадобится установить пакет для конкретной базы данных, например:
- SQL Server:
dotnet add package Hangfire.SqlServer - PostgreSQL:
dotnet add package Hangfire.PostgreSql - Redis:
dotnet add package Hangfire.Redis
После установки пакетов, необходимо настроить Hangfire в файле Program.cs (для ASP.NET Core) или Startup.cs.
Быстрый старт
Рассмотрим минимальный пример настройки и использования Hangfire в ASP.NET Core приложении.
Шаг 1: Настройка в Program.cs
using Hangfire;
using Hangfire.SqlServer;
var builder = WebApplication.CreateBuilder(args);
// Добавление Hangfire с хранилищем SQL Server
builder.Services.AddHangfire(configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage(builder.Configuration.GetConnectionString("HangfireConnection")));
// Добавление сервера Hangfire
builder.Services.AddHangfireServer();
var app = builder.Build();
// Включение Dashboard (панели мониторинга)
app.UseHangfireDashboard();
// Пример простого фонового задания
app.MapGet("/fire-and-forget", () =>
{
var jobId = BackgroundJob.Enqueue(() => Console.WriteLine("Hello from Hangfire!"));
return $"Job {jobId} has been enqueued.";
});
app.Run();
Шаг 2: Создание задачи
В примере выше мы использовали метод BackgroundJob.Enqueue. Это создает задачу типа "Fire-and-Forget" (запустил и забыл). Она будет выполнена немедленно в фоновом потоке.
Шаг 3: Запуск приложения
Перейдите по адресу /hangfire в вашем браузере, чтобы увидеть панель мониторинга. Перейдите по адресу /fire-and-forget, чтобы создать новую задачу. Вы увидите, как она появится в Dashboard и будет выполнена.
Основные методы/функции
Hangfire предоставляет богатый API для работы с фоновыми задачами. Рассмотрим 10 ключевых методов.
1. BackgroundJob.Enqueue
Описание: Создает задачу типа "Fire-and-Forget". Задача помещается в очередь и выполняется немедленно (как только освободится рабочий процесс).
Параметры:
Expression<Action>илиExpression<Func<Task>>— лямбда-выражение, описывающее выполняемый метод.string queue(необязательный) — имя очереди (по умолчанию "default").
Пример:
// Простая задача
BackgroundJob.Enqueue(() => Console.WriteLine("Task executed"));
// Задача с параметром
int userId = 123;
BackgroundJob.Enqueue(() => SendEmail(userId));
// Асинхронная задача
BackgroundJob.Enqueue(() => ProcessFileAsync("path/to/file"));
// Задача в конкретной очереди
BackgroundJob.Enqueue(() => HeavyComputation(), "critical");
2. BackgroundJob.Schedule
Описание: Создает отложенную задачу. Задача будет выполнена через указанный промежуток времени.
Параметры:
Expression<Action>илиExpression<Func<Task>>— лямбда-выражение.TimeSpan delay— задержка перед выполнением.string queue(необязательный) — имя очереди.
Пример:
// Задача через 1 час
BackgroundJob.Schedule(() => Console.WriteLine("Delayed task"), TimeSpan.FromHours(1));
// Задача через 10 минут
BackgroundJob.Schedule(() => SendReminderEmail("user@example.com"), TimeSpan.FromMinutes(10));
// Задача с использованием DateTimeOffset
BackgroundJob.Schedule(() => ProcessReport(), DateTimeOffset.Now.AddDays(1));
3. RecurringJob.AddOrUpdate
Описание: Создает или обновляет повторяющуюся задачу (cron job). Задача будет выполняться по заданному расписанию.
Параметры:
string recurringJobId— уникальный идентификатор задачи.Expression<Action>илиExpression<Func<Task>>— лямбда-выражение.string cronExpression— cron-выражение, описывающее расписание.string queue(необязательный) — имя очереди.
Пример:
// Каждую минуту
RecurringJob.AddOrUpdate("minute-job", () => Console.WriteLine("Every minute"), Cron.Minutely());
// Каждый день в полночь
RecurringJob.AddOrUpdate("daily-cleanup", () => CleanOldRecords(), Cron.Daily());
// Каждый час
RecurringJob.AddOrUpdate("hourly-report", () => GenerateHourlyReport(), "0 * * * *");
// Каждую пятницу в 18:00
RecurringJob.AddOrUpdate("weekly-backup", () => BackupDatabase(), "0 18 * * 5");
4. BackgroundJob.Delete
Описание: Удаляет задачу из очереди. Если задача уже выполняется, она не будет прервана, но повторные попытки (если они были запланированы) будут отменены.
Параметры:
string jobId— идентификатор задачи, полученный при создании.
Пример:
var jobId = BackgroundJob.Enqueue(() => SomeMethod());
// Позже, если нужно отменить
BackgroundJob.Delete(jobId);
5. BackgroundJob.Requeue
Описание: Перемещает задачу обратно в очередь для повторного выполнения. Полезно, если задача завершилась с ошибкой, и вы хотите попробовать снова вручную.
Параметры:
string jobId— идентификатор задачи.
Пример:
var jobId = BackgroundJob.Enqueue(() => UnstableMethod());
// Если задача упала, можно перезапустить
BackgroundJob.Requeue(jobId);
6. RecurringJob.RemoveIfExists
Описание: Удаляет повторяющуюся задачу по ее идентификатору.
Параметры:
string recurringJobId— идентификатор повторяющейся задачи.
Пример:
RecurringJob.RemoveIfExists("daily-cleanup");
7. RecurringJob.Trigger
Описание: Немедленно запускает повторяющуюся задачу вне зависимости от ее расписания.
Параметры:
string recurringJobId— идентификатор повторяющейся задачи.
Пример:
RecurringJob.Trigger("hourly-report"); // Запустить сейчас
8. IBackgroundJobClient.Create
Описание: Более продвинутый способ создания задачи. Позволяет задавать дополнительные параметры, такие как очередь, задержка, приоритет и т.д. Используется, когда нужно больше контроля.
Параметры:
Job job— объект, описывающий задачу.EnqueuedState state— начальное состояние задачи.
Пример:
var client = new BackgroundJobClient();
var job = Job.FromExpression(() => SomeMethod());
var state = new EnqueuedState("critical");
var jobId = client.Create(job, state);
9. IMonitoringApi
Описание: Интерфейс для программного мониторинга состояния задач. Позволяет получать статистику, список задач, детали ошибок и т.д.
Пример:
var monitor = JobStorage.Current.GetMonitoringApi();
var statistics = monitor.GetStatistics();
Console.WriteLine($"Enqueued: {statistics.Enqueued}");
Console.WriteLine($"Failed: {statistics.Failed}");
Console.WriteLine($"Succeeded: {statistics.Succeeded}");
// Получить последние 10 упавших задач
var failedJobs = monitor.FailedJobs(0, 10);
10. IBackgroundJobClient.ChangeState
Описание: Позволяет изменить состояние задачи. Например, можно перевести задачу из состояния "Failed" в "Enqueued" для повторного выполнения.
Параметры:
string jobId— идентификатор задачи.IState state— новое состояние.
Пример:
var client = new BackgroundJobClient();
client.ChangeState(jobId, new EnqueuedState());
Реальный практический пример использования
Рассмотрим сценарий: интернет-магазин. После оформления заказа необходимо выполнить несколько действий: отправить email покупателю, обновить складские остатки и создать задачу для службы доставки. Все эти операции должны выполняться асинхронно, чтобы не задерживать пользователя.
Создадим сервис для обработки заказа:
public class OrderProcessingService
{
private readonly IBackgroundJobClient _backgroundJobs;
public OrderProcessingService( Также в библиотеке
Генерация PDF на Go: обзор библиотек и примеры кода
Генератор QR-кодов на Go (Golang) с библиотекой go-qrcode
Авторизация и аутентификация в Swift (iOS/macOS): полное руководство
Elasticsearch клиент для TypeScript: @elastic/elasticsearch