কেন 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