Background Jobs¶
The Background Jobs module provides attributes for declaring durable, retryable background jobs with scheduling, plus interfaces for job management — enqueue, schedule, cancel, monitor, and retry from dead-letter.
Quick Start¶
using Deepstaging.Jobs;
using Deepstaging.Effects;
using LanguageExt;
// 1. Declare a job payload
[BackgroundJob(MaxRetries = 5, RetryDelayMs = 1000)]
public record SendWelcomeEmail(string UserId);
// 2. Write a handler
public static class EmailJobs
{
[JobHandler]
public static Eff<AppRuntime, Unit> Handle(SendWelcomeEmail job) =>
from _ in EmailEffects.Email.SendAsync<AppRuntime>(
job.UserId, "Welcome!", "Welcome to our platform.")
select unit;
}
// 3. Enqueue
from jobId in JobEffects.JobScheduler.EnqueueAsync<AppRuntime>(
new SendWelcomeEmail(userId))
select jobId;
Features¶
| Feature | Description |
|---|---|
| Retry & backoff | MaxRetries, RetryDelayMs with exponential backoff |
| Cron scheduling | [BackgroundJob(Cron = "0 */6 * * *")] for recurring jobs |
| Dead-letter | Failed jobs land in DLQ for inspection and manual retry |
| Status tracking | IJobStore — query by status (Pending, Running, Completed, Failed, DeadLetter) |
| Deduplication | DeduplicateBy prevents duplicate enqueue by payload property |
| Effects-native | Eff<RT, T> handlers with IHasJobEffects capability |
| Testability | TestJobScheduler with call recording, no real queue needed |
Sub-Pages¶
| Page | Description |
|---|---|
| Attributes | [BackgroundJob] and [JobHandler] reference — properties, cron format, examples |
| Generated Code | IJobScheduler, IJobStore, JobInfo, JobStatus, and dispatch composition |
| Effects Composition | Composing jobs with [Runtime] and [Uses], effect-wrapped scheduling |
| Testing | TestJobScheduler and TestJobStore — call recording and typed assertions |
Templating¶
Use Scriban templates for job failure alerts and dead-letter notifications. When a job exhausts its retries, the alert content can be rendered from a template with full job context.
{{- # Templates/Jobs/DeadLetterAlert.scriban-txt -}}
Job {{ job_type }} failed after {{ max_retries }} retries.
Job ID: {{ job_id }}
Last error: {{ last_error }}
Payload:
{{ for prop in payload }}
{{ prop.key }}: {{ prop.value }}
{{ end }}
// In a dead-letter handler
var body = Template.RenderText("Jobs/DeadLetterAlert", new
{
JobType = job.Type, JobId = job.Id, MaxRetries = job.MaxRetries,
LastError = job.LastError, Payload = job.PayloadProperties
});
For syntax reference and best practices, see Scriban Templating.
Diagnostics¶
| ID | Severity | Description |
|---|---|---|
| DSJOB01 | Error | JobHandler method must be static |
| DSJOB02 | Error | JobHandler has invalid signature (must return Eff<RT, Unit> with ≥1 parameter) |
| DSJOB03 | Warning | No [JobHandler] found for a [BackgroundJob] type |
| DSJOB04 | Warning | DeduplicateBy references a property that doesn't exist on the payload type |