Skip to main content

Job context

Every handler receives a worker.JobContext as its last argument. It carries per-execution metadata, the cancellation signal, a progress sink, and a job-scoped logger. The runtime constructs it — you never build one yourself.

JobContext embeds context.Context, so you can pass it (or its .Context) directly to any context-aware call.

func(ctx context.Context, p Payload, jc worker.JobContext) error {
jc.Logger.Info("starting")
jc.ReportProgress(0.25)
return doWork(ctx, p) // ctx is the cancelling context
}

Fields

FieldTypeMeaning
Contextcontext.ContextCancelled on timeout, shutdown, or a server cancel. Embedded — usable as the handler's ctx.
JobIDstringUnique id of this job execution. Use it as the idempotency key.
JobTypestringThe registered type string this job dispatched to.
Attemptint1-based attempt number.
MaxAttemptsintConfigured maximum attempts for this job.
EnqueuedAtstringWhen the job was enqueued (RFC-3339). Kept as a string and parsed on demand, so a malformed timestamp never disrupts dispatch.
Logger*slog.LoggerA logger pre-bound with the job id and type, so handler logs correlate automatically.

Cancellation

The embedded context is cancelled when:

  • the per-job timeout elapses,
  • the host is shutting down, or
  • the server returns a cancel directive on a heartbeat.

Cancellation is cooperative. Honour the context in every blocking call:

select {
case <-ctx.Done():
return ctx.Err()
case res := <-work:
return handle(res)
}

A handler that ignores its context keeps running until the server reclaims the job — and it holds a concurrency slot until it returns.

Progress

jc.ReportProgress(f) records fractional progress in [0, 1]. The value is surfaced on the next heartbeat and shown on the dashboard.

jc.ReportProgress(0.5)
  • Out-of-range or non-finite values (≤ 0, > 1, NaN, ±Inf) are ignored — progress is simply not reported until a valid value is set.
  • The latest valid value wins. There is no client-side requirement that progress only increase; the server treats reported progress as monotonic.

See Heartbeats & progress for the cadence details.

Logging

jc.Logger is a *slog.Logger bound with job_id and job_type, so anything you log inside the handler carries those fields:

jc.Logger.Info("charged customer", "amount_cents", 1999)

See also