#JobProvider
#Import
1import { JobProvider } from "alepha/api/jobs";
#Overview
Coordinates cron and push jobs with a durable outbox table and a single
reconciliation sweep. The actual delivery channel (queue / direct) is
abstracted behind JobDispatcher, substituted by DI:
- DirectJobDispatcher (default, registered by
AlephaApiJobs) - runs the handler in-process right afterpush()returns. - QueueJobDispatcher (registered by
AlephaApiJobsQueue): sends the executionId throughAlephaQueueso a pool of workers can pick it up.
Push flow: push() → INSERT row (pending) → dispatcher.dispatch(jobName, id) worker → claim → UPDATE running → handler → UPDATE ok (or DELETE when successes are not recorded) → UPDATE error (or DELETE) / scheduled (retry) on failure
Cron flow: scheduler tick → claim the instant → acquire lock → executeInline (no retry) → enqueue + dispatch (retry declared)
Sweep responsibilities (every sweepCron), one per status, declared in
sweepTable():
scheduledwithscheduledAt <= now→ pending + dispatchpendinguntouched forstaleThreshold→ re-dispatchrunningpast its lease → failed, then the retry policy
Trim runs on its own cron (trimCron, default hourly):
- rows of a job name nothing registers are purged first, every status
(a renamed job loses its rows, see
purgeUnregistered) - then each job's retention: per status, rows past the newest
lastor completed more thandaysago (seeJobRetentionProvider) - decoupled from sweep because trim cost scales with job count, not retry latency - running it every sweep is wasted work for most apps.