Skip to main content

Job context

Every handler receives a JobContext as its last argument. The worker constructs it for each execution — you never build one yourself.

from zeridion_flare.worker import JobContext

@worker.job("SendWelcomeEmail")
def send_welcome(payload, ctx: JobContext) -> None:
ctx.logger.info("starting job %s", ctx.job_id)
ctx.report_progress(0.5)
if ctx.is_cancelled():
return
...
ctx.report_progress(1.0)

Metadata

AttributeTypeDescription
job_idstrUnique id for this execution.
attemptintWhich attempt this is (starts at 1).
max_attemptsintAttempt ceiling for the job.
enqueued_atdatetime | NoneWhen the job was enqueued (time-zone aware; None if the timestamp was missing or unparseable).
job_typestrThe job-type string for this execution.
loggerlogging.LoggerA logger pre-bound with the job's id and type so handler logs correlate automatically.

Reporting progress

ctx.report_progress(0.25)

Progress is a fraction from 0.0 to 1.0 and surfaces on the dashboard while the job runs. The latest value rides the next heartbeat. Values outside the range are ignored — 0 or negative is treated as "no update", and anything above 1.0 is clamped to 1.0. The most recent valid value wins.

Cancellation

A job can be cancelled while it runs — when it exceeds its timeout, when the server asks to cancel it, or when the worker is shutting down. Because Python threads cannot be safely killed, cancellation is cooperative: your handler has to check for it.

@worker.job("ProcessLargeBatch")
def process_batch(payload, ctx: JobContext) -> None:
for row in rows:
if ctx.is_cancelled():
return # stop promptly
do_work(row)

# Prefer the interruptible sleep over time.sleep so a cancel is noticed:
if ctx.cancellation.sleep(5.0):
return # woke early because cancelled

The cancellation handle exposes:

MemberBehaviour
ctx.is_cancelled()True once cancellation has been requested.
ctx.raise_if_cancelled()Raises if cancellation has been requested.
ctx.cancellation.sleep(seconds)Interruptible sleep; returns True if cancelled before the time elapsed.
ctx.cancellation.register(closer)Registers a callback (e.g. to close a socket) invoked when cancellation is requested.

A CPU-bound handler that never yields cannot be interrupted. It keeps running until it finishes, after which the worker reclaims its slot. The server has its own reclaim window for a job that stops reporting, so the job will be retried elsewhere even if a wedged handler can't be stopped locally. For hard, immediate cancellation, run such work in a separate process.

Idempotency

Because the final acknowledgement is best-effort, a job can be delivered more than once. Use ctx.job_id to make side effects idempotent — record that the work for an id was done, and skip it on a redelivery.

See also