Skip to content

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