Step 10 of 11
BackgroundService with PeriodicTimer, QuestPDF, health checks, Docker, tests
Workshop 4: Background service สร้าง PDF payslip — ฝึก IHostedService, Docker, health checks, xUnit
Scenario: The payroll API works, but generating PDF payslips takes too long to do synchronously. The HR team wants payslips generated automatically at the end of each month and downloadable anytime. Build a background service that handles this.
A BackgroundService that runs on a schedule, generates PDF payslips for all active employees, stores them on disk, and exposes a health check endpoint. The whole service runs in Docker.
BackgroundService with PeriodicTimerAddHealthChecks, MapHealthChecks)Create a PayslipGeneratorService : BackgroundService that:
./payslips/{year}/{month}/{employeeId}.pdfILogger<T>)PDF generation — use QuestPDF (MIT license, no AGPL):
dotnet add package QuestPDF
Include: employee name, department, gross salary, tax, SSO, provident fund, net pay, pay period
Add health checks:
builder.Services.AddHealthChecks()
.AddDbContextCheck<AppDbContext>();
app.MapHealthChecks("/health");
Dockerize with a multi-stage Dockerfile:
mcr.microsoft.com/dotnet/sdk:9.0mcr.microsoft.com/dotnet/aspnet:9.0/app/payslipsWrite at least one unit test verifying the payroll calculation logic and one integration test verifying the service starts and responds to health checks.
GET /api/payslips/{employeeId}/latest endpoint that returns the most recent PDFappsettings.json for the generation schedule (use IOptions<PayrollSettings>)This background service is the IHostedService component of your Payroll & Benefits Management System (see ADR-004 in the final workshop spec). It demonstrates the scheduled payroll run that triggers RabbitMQ events (payroll.calculated, payroll.run.completed) in the full system.