Changelog
Version v0.14.0
What’s Changed
Features
- Caller-supplied job IDs (breaking):
startChain,startChains, and the workercontinueWithcallback now accept an optionalidthat becomes the new chain root (or continuation) job ID. State adapters accept a newvalidateIdpredicate that runs on both adapter-generated and caller-supplied IDs; failures throw the newInvalidJobIdError. When deduplication fires, the existing row’s ID wins over a caller-suppliedid(the returned chain carriesdeduplicated: true). - Aligned adapter ID-generation options (breaking): both PostgreSQL and SQLite adapters now expose a
generateIdfunction. PostgreSQL’sidDefault(SQL expression) is removed in favor of JS-side generation; SQLite’sidGeneratoris renamed togenerateId. A new PostgreSQL migration dropsDEFAULT gen_random_uuid()from theidcolumn. Existing UUID generation behavior is unchanged for default configurations.
Bug Fixes
scheduled_atis now an honest eligibility floor: state adapters clampscheduled_attoMAX(requested, now())oncreateJobs,rescheduleJob, andunblockJobs. Previously, jobs with a pastscheduled_at(or blocked-since-creation jobs whose originalscheduled_atwent stale while they waited) would jump to the front of the acquisition queue ahead of jobs that genuinely became ready earlier.unblockJobsnow preserves a futurescheduled_atset at job creation (it previously reset tonow()unconditionally);triggerJobscontinues to re-anchor tonow()as an explicit reset. Applies to PostgreSQL, SQLite, and in-process adapters; no schema migration or backfill required.lastAttemptErrorcleared on success: when a job completes successfully after a previously failed attempt,completeJobnow resetslast_attempt_errortoNULLalongside the existing status/output/lease updates. Completed rows no longer carry over an error string from a prior failed attempt.requiredAttemptMiddlewaretype fix: a spurious type error fromcreateInProcessWorker’srequiredAttemptMiddlewarecheck is fixed when middleware is typed against a user-suppliedStateAdapteralias (e.g.AttemptMiddleware<MyStateAdapter>). Valid processor slices were being flagged as missing required middleware. Runtime behavior was unaffected; this is a type-only fix.BaseTxContexttightened: changed from{}toRecord<string, unknown>. The previous{}constraint accepted any non-nullish value (string, number, function), letting customStateAdapterauthors pick a non-objectTTxContextwithout a type error. All built-in adapters are already object-shaped, so no runtime behavior changes.
Migration Notes
- PostgreSQL: replace
idDefault: "gen_random_uuid()"withgenerateId: () => crypto.randomUUID()(this is the default and can be omitted). - PostgreSQL: replace
idDefault: "'job.' || gen_random_uuid()::text"withgenerateId: () => `job.${crypto.randomUUID()}`. - SQLite: rename
idGeneratoroption togenerateId. - Custom state adapter implementations must accept an optional
idper entry increateJobsand apply their ownvalidateIdpredicate.
Packages
All packages released at 0.14.0: queuert, @queuert/postgres, @queuert/sqlite, @queuert/redis, @queuert/nats, @queuert/otel, @queuert/dashboard.