Skip to content

Execution model

Job separates task intent from task delivery. Your app declares task handlers. The Job Product Worker records run state, sends delivery messages, executes handlers from Queue events, and records attempt results.

Terminal window
jobs.enqueue(...)
-> Job Product RPC
-> layeron_job_runs insert
-> Queue Product send
-> Job Product Worker queue event
-> layeron_job_attempts insert
-> task handler
-> run status update

A task is a named handler:

Terminal window
jobs.task("resize-image", {}, async (payload, ctx) => {
await resizeImage(payload.objectKey)
})

Task names are stable product metadata. Choose names that describe the work, such as deliver-webhook, send-email, resize-image, or sync-provider.

A run is one execution request:

Terminal window
const run = await jobs.enqueue("resize-image", {
objectKey: "uploads/avatar.png",
})

Run states:

StatusMeaning
queuedThe run is ready for delivery.
scheduledThe run has a future execution time.
runningA task handler is executing.
succeededThe task handler completed.
retryingThe latest attempt failed and another attempt is scheduled.
canceledThe run was canceled.
dead_letteredThe run exhausted attempts.

An attempt is one try at a run. Attempts have their own IDs and timing. A run with attempts: 5 can produce up to five attempt records.

The task context exposes attempt metadata:

Terminal window
jobs.task("sync-provider", {}, async (payload, ctx) => {
await syncProvider(payload.accountId, {
runId: ctx.runId,
attempt: ctx.attempt,
})
})

Job uses Queue for delivery. Queue handles delayed delivery and wakes the Job Product Worker. Job owns the run state and retry decision.

This split keeps task execution durable:

  • enqueue returns after the run is recorded and delivery is requested.
  • Queue delivery can happen outside the original request.
  • failed attempts update Job state before retry.
  • exhausted attempts become dead_lettered for inspection and replay.

Use idempotencyKey when the same business event can enqueue the same work more than once:

Terminal window
await jobs.enqueue("deliver-webhook", payload, {
idempotencyKey: `webhook:${payload.endpointId}:${payload.eventId}`,
})

When the key already exists for the Job instance, Job returns the existing run metadata with deduped: true.