Core concepts
Jobs, queues, handlers, schedules, workers and leases. The six ideas the rest of the docs build on.
Jobs
A job is one unit of work: a handler name, a JSON payload, a queue and a time to run. Jobs are immutable except for their state. Sextant gives each one an id such as job_8f3k2m9q.
A job can carry an idempotency_key. Creating a second job with the same key within 24 hours returns the first job instead, which makes it safe to retry the request that creates it.
Queues
A queue is a named line of jobs with its own settings: how many run at once (concurrency), how often they are retried (max_attempts, backoff) and how long a handler may take (timeout). Queues are declared in the config file, not created through the API.
Use separate queues when work differs in urgency or cost. A slow reports queue should not delay a fast emails queue.
Handlers
A handler is the code that does the work, registered under a name. There are two ways to run one:
- In your application, with an SDK. Your process connects as a worker and registers functions.
- As a command, declared under
[handlers.<name>]in the config.sextant workerstarts it per job, with the payload on standard input.
Schedules
A schedule creates jobs on a cron expression or a fixed interval. The server evaluates schedules, so they keep firing while workers restart. See Scheduling jobs.
Workers and leases
A worker pulls jobs from the queues it serves. When it takes a job it holds a lease, 30 seconds by default, and renews it with a heartbeat while the handler runs. If the worker dies, the lease expires and the job goes back to queued with the attempt counted.
Runs and attempts
Every time a worker starts a job, Sextant records an attempt with the worker, the start and end time, the result and the error. The sequence of attempts is the job’s timeline, shown by sextant inspect. The words run and attempt mean the same thing in these docs and in the metrics.
Chaining jobs
Sextant has no workflow language. To run job B after job A, create B from A’s handler once its work is done:
import { defineHandler } from '@sextant/node';
export default defineHandler('charge-card', async (job, ctx) => {
const charge = await billing.charge(job.payload.orderId);
await ctx.jobs.create({
queue: 'emails',
handler: 'send-receipt',
payload: { orderId: job.payload.orderId, chargeId: charge.id },
idempotencyKey: `receipt-${job.payload.orderId}`,
});
});The next page is how a job moves between states: Job lifecycle.