JobContext
Runtime context injected into every job execution. Provides metadata about the current job, a cancellation token, a scoped logger, and a progress reporting callback. Never construct this class yourself — the worker creates it automatically.
Namespace: Zeridion.Flare · Assembly: Zeridion.Flare.dll
public sealed class JobContext
{
public required string JobId { get; init; }
public required int AttemptNumber { get; init; }
public required int MaxAttempts { get; init; }
public required DateTimeOffset EnqueuedAt { get; init; }
public required CancellationToken CancellationToken { get; init; }
public required ILogger Logger { get; init; }
public Func<double, Task> ReportProgress { get; init; } = _ => Task.CompletedTask;
}
Properties
| Property | Type | Description |
|---|---|---|
JobId | string | Unique identifier assigned by the server when the job was created. |
AttemptNumber | int | Current attempt number, starting at 1. Increments on each retry. |
MaxAttempts | int | Maximum number of attempts configured for this job. |
EnqueuedAt | DateTimeOffset | UTC timestamp when the job was originally enqueued. |
CancellationToken | CancellationToken | Cancelled on host shutdown, job timeout, or explicit cancellation. |
Logger | ILogger | Logger scoped to this job execution with structured context. |
ReportProgress | Func<double, Task> | Report progress from 0.0 to 1.0, visible in the dashboard. |
CancellationToken
The CancellationToken is a linked token that fires in any of these scenarios:
- Host shutdown — the application is stopping gracefully (
IHostApplicationLifetime) - Job timeout — the configured timeout period has elapsed since the worker started processing
- Explicit cancellation — a cancel request was received while the job was processing
Pass this token to every async operation inside your job — HTTP calls, database queries, file I/O — so work stops promptly when cancellation is requested:
public async Task ExecuteAsync(OrderPayload payload, JobContext ctx)
{
var response = await _httpClient.PostAsync(url, content, ctx.CancellationToken);
await _db.SaveChangesAsync(ctx.CancellationToken);
}
The worker sends heartbeats to the API at an interval of TimeoutSeconds / 3 (minimum 10 seconds). If no heartbeat arrives within the timeout window, the server marks the job as stuck and makes it available for another worker to claim.
ReportProgress
Call ReportProgress with a value between 0.0 and 1.0 to update the job's progress in the dashboard. This is useful for long-running jobs that process items in a loop:
public async Task ExecuteAsync(BatchPayload payload, JobContext ctx)
{
for (int i = 0; i < payload.Items.Count; i++)
{
await ProcessItem(payload.Items[i], ctx.CancellationToken);
await ctx.ReportProgress((double)(i + 1) / payload.Items.Count);
}
}
ReportProgress is safe to call at any frequency. In the current SDK version it is a no-op delegate — progress values are not yet sent to the API. This will be wired in a future release. Calling it now is forward-compatible and has no performance cost.
Usage example
A job that uses all context properties:
[JobConfig(MaxAttempts = 5, TimeoutSeconds = 600)]
public class ProcessLargeDataset : IJob<DatasetPayload>
{
private readonly IDataStore _store;
public ProcessLargeDataset(IDataStore store) => _store = store;
public async Task ExecuteAsync(DatasetPayload payload, JobContext ctx)
{
ctx.Logger.LogInformation(
"Starting job {JobId}, attempt {Attempt}/{Max}, enqueued at {EnqueuedAt}",
ctx.JobId, ctx.AttemptNumber, ctx.MaxAttempts, ctx.EnqueuedAt);
var records = await _store.GetRecordsAsync(payload.DatasetId, ctx.CancellationToken);
for (int i = 0; i < records.Count; i++)
{
ctx.CancellationToken.ThrowIfCancellationRequested();
await _store.ProcessAsync(records[i], ctx.CancellationToken);
await ctx.ReportProgress((double)(i + 1) / records.Count);
}
ctx.Logger.LogInformation("Job {JobId} completed, processed {Count} records",
ctx.JobId, records.Count);
}
}
See also
- IJob<T> — the job interface that receives
JobContext - IRecurringJob — recurring jobs also receive
JobContext - Progress reporting — patterns for reporting progress in batch jobs