Background Jobs — Hangfire / Hosted Services

লেসন ৩৯ / ৫০

কেন Background Job?

Email পাঠানো, report generate — request-এ block না করে background-এ চালান।

BackgroundService (Built-in)

public class EmailQueueService : BackgroundService {
    private readonly ILogger<EmailQueueService> _logger;
    private readonly IServiceScopeFactory _scopeFactory;

    public EmailQueueService(ILogger<EmailQueueService> l, IServiceScopeFactory s) {
        _logger = l; _scopeFactory = s;
    }

    protected override async Task ExecuteAsync(CancellationToken stop) {
        while (!stop.IsCancellationRequested) {
            using var scope = _scopeFactory.CreateScope();
            var ctx = scope.ServiceProvider.GetRequiredService<AppDbContext>();
            var pending = await ctx.EmailQueue.Where(e => !e.Sent).Take(10).ToListAsync(stop);
            foreach (var e in pending) {
                await SendEmail(e);
                e.Sent = true;
            }
            await ctx.SaveChangesAsync(stop);
            await Task.Delay(TimeSpan.FromSeconds(30), stop);
        }
    }
}

// Program.cs
builder.Services.AddHostedService<EmailQueueService>();

Timed Hosted Service

public class CleanupService : IHostedService, IDisposable {
    private Timer? _timer;
    public Task StartAsync(CancellationToken ct) {
        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromHours(1));
        return Task.CompletedTask;
    }
    private void DoWork(object? state) {
        // Cleanup logic
    }
    public Task StopAsync(CancellationToken ct) {
        _timer?.Change(Timeout.Infinite, 0);
        return Task.CompletedTask;
    }
    public void Dispose() => _timer?.Dispose();
}

Hangfire ⭐ (Persistent Job Queue)

dotnet add package Hangfire.AspNetCore
dotnet add package Hangfire.SqlServer

// Program.cs
builder.Services.AddHangfire(c => c
    .UseSqlServerStorage(builder.Configuration.GetConnectionString("Default")));
builder.Services.AddHangfireServer();

var app = builder.Build();
app.UseHangfireDashboard("/hangfire");   // GUI: /hangfire

Hangfire Job Types

// 1. Fire-and-forget
BackgroundJob.Enqueue(() => SendEmail("user@x.com", "Hi"));

// 2. Delayed
BackgroundJob.Schedule(() => SendReminder(123), TimeSpan.FromHours(1));

// 3. Recurring
RecurringJob.AddOrUpdate(
    "daily-report",
    () => GenerateDailyReport(),
    Cron.Daily);

// 4. Continuation
var id = BackgroundJob.Enqueue(() => ProcessOrder(101));
BackgroundJob.ContinueJobWith(id, () => SendInvoice(101));

Quartz.NET (Alternative)

dotnet add package Quartz.Extensions.Hosting
// Cron-based jobs, more flexible scheduling