@zmdb/jobs 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # @zmdb/jobs
2
+
3
+ Typed queues, workers, dead letters, scheduling, leases, and explicit provider ports for zmdb applications.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ yarn add @zmdb/jobs@1.0.0-beta.1
9
+ ```
10
+
11
+ The package is ESM-only and requires Node.js 26 or later. It has no third-party runtime peer. `yarn add zmdb@1.0.0-beta.1` does not install it, and there is no `zmdb/jobs` facade.
12
+
13
+ ## Choose the capability and its storage
14
+
15
+ The default [SQLite HTTP application](https://ambasta.github.io/zmdb/docs/web-overview.html) starts with `yarn add zmdb@1.0.0-beta.1`. Add jobs when the application needs background work:
16
+
17
+ | Choice | Install | Public imports |
18
+ | --------------------------------------- | ------------------------------------------------------------------------------ | ----------------------------------------- |
19
+ | Portable queues and scheduling | `yarn add @zmdb/jobs@1.0.0-beta.1` | `@zmdb/jobs`, `@zmdb/jobs/schedule` |
20
+ | SQLite jobs, including the memory store | `yarn add @zmdb/jobs@1.0.0-beta.1 @zmdb/jobs-sqlite@1.0.0-beta.1` | `@zmdb/jobs`, `@zmdb/jobs-sqlite` |
21
+ | PostgreSQL jobs | `yarn add @zmdb/jobs@1.0.0-beta.1 @zmdb/jobs-postgres@1.0.0-beta.1 pg@^8.23.0` | `@zmdb/jobs`, `@zmdb/jobs-postgres`, `pg` |
22
+
23
+ The portable install supplies behavior and provider ports. Queue and worker constructors require an explicit `store` and throw `TypeError` when it is missing; they never choose SQLite automatically.
24
+ Per-replica schedules can run without a database. A cluster schedule requires a supplied `LeaseStore` and is refused before startup when it is missing. These package boundaries let applications select
25
+ storage and upgrade providers independently while using the same jobs APIs and application lifecycle.
26
+
27
+ ## Migrations and ownership
28
+
29
+ | Constructor | Before starting work | Resource ownership |
30
+ | ----------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
31
+ | `createMemoryJobStore()` from `@zmdb/jobs-sqlite` | Creates and migrates a fresh memory database automatically | The store owns and closes that database |
32
+ | `createSqliteJobStore(database)` from `@zmdb/jobs-sqlite` | Apply the exported `jobsSqliteMigrations` to the caller's database | Closing the store leaves the supplied database open |
33
+ | `createPgJobStore(poolOrClient)` from `@zmdb/jobs-postgres` | Apply the exported `jobsPostgresMigrations` to the selected PostgreSQL database | The caller owns the supplied pool/client; the adapter releases only connections it acquires internally |
34
+
35
+ Durable providers do not apply migrations automatically. Their stores also implement the scheduler's lease port, so a cluster scheduler can use the selected store as `leases`. Distinct replicas need
36
+ shared storage; a fresh process-local memory store cannot coordinate them.
37
+
38
+ Include a store in `jobsExtension({ workers, schedulers, stores })` to close its adapter after schedulers and workers stop. Await `app[Symbol.asyncDispose]()` before closing a caller-owned database or
39
+ pool. If a store is managed outside the extension, the caller closes it after background work stops, as in the complete server example below.
40
+
41
+ ## Entry points
42
+
43
+ - `@zmdb/jobs` — queues, workers, the common clock, lifecycle integration, and the complete convenience surface
44
+ - `@zmdb/jobs/schedule` — cron and interval decorators, schedulers, and the lease-store port
45
+
46
+ Workers and schedulers are explicit instances. Pass them to `jobsExtension({ workers, schedulers, stores })` to start after application bootstrap and stop under the application's bounded grace period.
47
+
48
+ ```ts
49
+ import { createApplication, Module } from '@zmdb/app';
50
+ import { jobsExtension } from '@zmdb/jobs';
51
+
52
+ @Module({ controllers: [] })
53
+ class Application {}
54
+
55
+ const app = createApplication(Application, {
56
+ extensions: [jobsExtension({ workers: [], schedulers: [] })],
57
+ });
58
+ await app.init();
59
+ await app[Symbol.asyncDispose]();
60
+ ```
61
+
62
+ The [complete server example](https://ambasta.github.io/zmdb/docs/web-overview.html) creates a real SQLite worker and supplies this extension to `createApp`, so HTTP and jobs share one application
63
+ lifecycle.
64
+
65
+ Replace the empty arrays with the workers and schedulers owned by that application. The extension uses the same startup, rollback, reverse shutdown, and grace deadline as every other `@zmdb/app`
66
+ extension.
67
+
68
+ The default package has no `pg` peer. SQLite workers add `@zmdb/jobs-sqlite@1.0.0-beta.1`, which owns both durable and memory storage. PostgreSQL workers add `@zmdb/jobs-postgres@1.0.0-beta.1` and
69
+ `pg@^8.23.0`; that adapter borrows a caller-owned pool or client and never closes the supplied resource; it releases only connections it acquires internally.
70
+
71
+ ## Alpha migration
72
+
73
+ Update the selected dependency and import together:
74
+
75
+ | Removed or branch-only import | Current import | Required selection |
76
+ | ----------------------------- | ----------------------------------------------- | ---------------------------------------------- |
77
+ | `@zmdb/jobs/memory` | `createMemoryJobStore` from `@zmdb/jobs-sqlite` | Add `@zmdb/jobs-sqlite` alongside `@zmdb/jobs` |
78
+ | `zmdb/jobs` | `@zmdb/jobs` | Add `@zmdb/jobs` explicitly |
79
+ | `zmdb/jobs/schedule` | `@zmdb/jobs/schedule` | Add `@zmdb/jobs` explicitly |
80
+ | `zmdb/jobs/memory` | `createMemoryJobStore` from `@zmdb/jobs-sqlite` | Add both jobs and the SQLite provider |
81
+
82
+ The memory constructor now belongs to the SQLite provider. Keep portable queues, workers and schedules imported from `@zmdb/jobs`; supply the chosen provider through its public ports. The retired
83
+ entries have no runtime forwarders. The [queues guide](https://ambasta.github.io/zmdb/docs/web-queues.html) covers provider migrations, transactions and bounded shutdown.
84
+
85
+ ## License
86
+
87
+ GNU General Public License v3.0 or later (GPL-3.0-or-later).
@@ -0,0 +1,15 @@
1
+ import type { ApplicationExtension } from '@zmdb/app';
2
+ import type { JobStoreResource, Worker } from './queues/index.js';
3
+ import type { Scheduler } from './schedule/index.js';
4
+ /**
5
+ * Start and stop one application's explicit background-work components.
6
+ *
7
+ * Workers start first so a scheduled enqueue always has a consumer. Shutdown
8
+ * reverses that order so no scheduler can add work after worker drain begins.
9
+ */
10
+ export declare function jobsExtension(options: {
11
+ readonly workers?: readonly Worker[];
12
+ readonly schedulers?: readonly Scheduler[];
13
+ readonly stores?: readonly JobStoreResource[];
14
+ }): ApplicationExtension;
15
+ //# sourceMappingURL=extension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAOrD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC/C,GAAG,oBAAoB,CAsBvB"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Start and stop one application's explicit background-work components.
3
+ *
4
+ * Workers start first so a scheduled enqueue always has a consumer. Shutdown
5
+ * reverses that order so no scheduler can add work after worker drain begins.
6
+ */
7
+ export function jobsExtension(options) {
8
+ const workers = Object.freeze([...(options.workers ?? [])]);
9
+ const schedulers = Object.freeze([...(options.schedulers ?? [])]);
10
+ const stores = [...new Set(options.stores ?? [])];
11
+ const enteredWorkers = [];
12
+ const enteredSchedulers = [];
13
+ let started = false;
14
+ let stopped;
15
+ return {
16
+ name: '@zmdb/jobs',
17
+ start() {
18
+ if (started)
19
+ return;
20
+ started = true;
21
+ startAll(workers, enteredWorkers);
22
+ startAll(schedulers, enteredSchedulers);
23
+ },
24
+ stop({ graceMs }) {
25
+ stopped ??= stopAll(enteredSchedulers, enteredWorkers, stores, graceMs);
26
+ return stopped;
27
+ },
28
+ };
29
+ }
30
+ function startAll(participants, entered) {
31
+ for (const participant of participants) {
32
+ entered.push(participant);
33
+ participant.start();
34
+ }
35
+ }
36
+ async function stopAll(schedulers, workers, stores, graceMs) {
37
+ if (!Number.isSafeInteger(graceMs) || graceMs < 0 || graceMs > 2_147_483_647) {
38
+ throw new RangeError('@zmdb/jobs: graceMs must be a non-negative safe integer');
39
+ }
40
+ const deadline = Date.now() + graceMs;
41
+ const errors = [];
42
+ const stops = [
43
+ ...schedulers
44
+ .toReversed()
45
+ .map(participant => (remaining) => participant.onShutdown({ graceMs: remaining })),
46
+ ...workers.toReversed().map(participant => (remaining) => participant.onShutdown({ graceMs: remaining })),
47
+ ...stores.toReversed().map(store => (remaining) => store.close({ graceMs: remaining })),
48
+ ];
49
+ for (const stop of stops) {
50
+ let timer;
51
+ try {
52
+ const remaining = Math.max(0, deadline - Date.now());
53
+ const work = Promise.resolve(stop(remaining));
54
+ await Promise.race([
55
+ work,
56
+ new Promise((_resolve, reject) => {
57
+ timer = setTimeout(() => reject(new DOMException('@zmdb/jobs: shutdown deadline exceeded', 'TimeoutError')), remaining);
58
+ }),
59
+ ]);
60
+ }
61
+ catch (error) {
62
+ errors.push(error);
63
+ }
64
+ finally {
65
+ clearTimeout(timer);
66
+ }
67
+ }
68
+ if (errors.length === 0)
69
+ return;
70
+ if (errors.length === 1)
71
+ throw errors[0];
72
+ throw new AggregateError(errors, '@zmdb/jobs: background work shutdown failed');
73
+ }
74
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { jobsExtension } from './extension.js';
2
+ export { createQueue, createWorker } from './queues/index.js';
3
+ export { Cron, Interval, createScheduler, schedulesOf } from './schedule/index.js';
4
+ export type { AnyJobHandler, Backoff, Clock, DeadJob, DeadReason, EnqueueOptions, JobContext, ClaimedJob, JobCandidate, JobEnqueue, JobEnqueuer, JobEnqueueResult, JobSettlement, JobStoreResource, JobStoreMigration, JobHandler, JobOutcome, JobStore, Queue, QueueOptions, RetryPolicy, RunReport, Worker, WorkerOptions, } from './queues/index.js';
5
+ export type { IntervalOptions, LeaseStore, ScheduleDef, Scheduler, SchedulerOptions, SkippedRun, TaskDecorator, TaskOptions, TaskRuns, } from './schedule/index.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACnF,YAAY,EACV,aAAa,EACb,OAAO,EACP,KAAK,EACL,OAAO,EACP,UAAU,EACV,cAAc,EACd,UAAU,EACV,UAAU,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,UAAU,EACV,QAAQ,EACR,KAAK,EACL,YAAY,EACZ,WAAW,EACX,SAAS,EACT,MAAM,EACN,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,eAAe,EACf,UAAU,EACV,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,WAAW,EACX,QAAQ,GACT,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ // @zmdb/jobs — queues, workers, scheduling and app lifecycle integration.
2
+ export { jobsExtension } from './extension.js';
3
+ export { createQueue, createWorker } from './queues/index.js';
4
+ export { Cron, Interval, createScheduler, schedulesOf } from './schedule/index.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,191 @@
1
+ export interface Clock {
2
+ now(): number;
3
+ sleep(ms: number, signal: AbortSignal): Promise<void>;
4
+ }
5
+ export interface JobEnqueue {
6
+ readonly id: string;
7
+ readonly name: string;
8
+ readonly payload: string;
9
+ readonly enqueuedAt: Date;
10
+ readonly availableAt: Date;
11
+ readonly dedupeKey?: string;
12
+ }
13
+ export type JobEnqueueResult = {
14
+ readonly kind: 'inserted';
15
+ readonly jobId: string;
16
+ } | {
17
+ readonly kind: 'duplicate';
18
+ readonly jobId: string;
19
+ };
20
+ export interface JobEnqueuer {
21
+ enqueue(job: JobEnqueue): Promise<JobEnqueueResult>;
22
+ }
23
+ export interface JobCandidate {
24
+ readonly id: string;
25
+ readonly name: string;
26
+ readonly enqueuedAt: Date;
27
+ }
28
+ export interface ClaimedJob extends JobCandidate {
29
+ readonly payload: string;
30
+ readonly attempts: number;
31
+ readonly dedupeKey?: string;
32
+ readonly holder: string;
33
+ }
34
+ export type JobSettlement = {
35
+ readonly kind: 'done';
36
+ readonly jobId: string;
37
+ readonly holder: string;
38
+ readonly idempotencyKey: string;
39
+ readonly completedAt: Date;
40
+ } | {
41
+ readonly kind: 'retry';
42
+ readonly jobId: string;
43
+ readonly holder: string;
44
+ readonly attempts: number;
45
+ readonly availableAt: Date;
46
+ readonly detail: string;
47
+ } | {
48
+ readonly kind: 'dead';
49
+ readonly jobId: string;
50
+ readonly holder: string;
51
+ readonly attempts: number;
52
+ readonly reason: DeadReason;
53
+ readonly detail: string;
54
+ readonly deadAt: Date;
55
+ } | {
56
+ readonly kind: 'release';
57
+ readonly jobId: string;
58
+ readonly holder: string;
59
+ readonly availableAt: Date;
60
+ };
61
+ export interface JobStore extends JobEnqueuer {
62
+ candidates(options: {
63
+ readonly now: Date;
64
+ readonly limit: number;
65
+ }): Promise<readonly JobCandidate[]>;
66
+ claim(options: {
67
+ readonly ids: readonly string[];
68
+ readonly holder: string;
69
+ readonly now: Date;
70
+ readonly leaseUntil: Date;
71
+ }): Promise<readonly ClaimedJob[]>;
72
+ completed(key: string): Promise<boolean>;
73
+ settle(settlement: JobSettlement): Promise<boolean>;
74
+ listDead(options: {
75
+ readonly limit: number;
76
+ readonly reason?: DeadReason;
77
+ }): Promise<readonly DeadJob[]>;
78
+ replay(jobId: string, availableAt: Date): Promise<boolean>;
79
+ }
80
+ export interface JobStoreResource {
81
+ close(options?: {
82
+ readonly graceMs: number;
83
+ }): void | Promise<void>;
84
+ }
85
+ export interface JobStoreMigration {
86
+ readonly version: number;
87
+ readonly name: string;
88
+ readonly up: string;
89
+ readonly down: string;
90
+ }
91
+ export type Backoff = {
92
+ readonly kind: 'fixed';
93
+ readonly delayMs: number;
94
+ } | {
95
+ readonly kind: 'exponential';
96
+ readonly baseMs: number;
97
+ readonly ceilingMs: number;
98
+ };
99
+ export interface RetryPolicy {
100
+ readonly attempts: number;
101
+ readonly backoff: Backoff;
102
+ }
103
+ export type DeadReason = 'invalid-payload' | 'unknown-name' | 'attempts-exhausted';
104
+ export type JobOutcome = {
105
+ readonly kind: 'done';
106
+ } | {
107
+ readonly kind: 'retry';
108
+ readonly afterMs: number;
109
+ } | {
110
+ readonly kind: 'dead';
111
+ readonly reason: DeadReason;
112
+ readonly detail: string;
113
+ };
114
+ export interface JobContext {
115
+ readonly jobId: string;
116
+ readonly name: string;
117
+ readonly attempt: number;
118
+ readonly enqueuedAt: Date;
119
+ readonly idempotencyKey: string;
120
+ readonly signal: AbortSignal;
121
+ }
122
+ export interface JobHandler<M, K extends keyof M & string> {
123
+ readonly name: K;
124
+ readonly validate: (raw: unknown) => M[K];
125
+ handle(payload: M[K], ctx: JobContext): Promise<void>;
126
+ readonly concurrency?: number;
127
+ readonly timeoutMs?: number;
128
+ readonly retries?: RetryPolicy;
129
+ }
130
+ export type AnyJobHandler<M> = {
131
+ readonly [K in keyof M & string]: JobHandler<M, K>;
132
+ }[keyof M & string];
133
+ export interface EnqueueOptions {
134
+ readonly delayMs?: number;
135
+ readonly dedupeKey?: string;
136
+ }
137
+ export interface Queue<M> {
138
+ enqueue<K extends keyof M & string>(name: K, payload: M[K], opts?: EnqueueOptions): Promise<string>;
139
+ enqueueInTransaction<K extends keyof M & string>(tx: JobEnqueuer, name: K, payload: M[K], opts?: EnqueueOptions): Promise<string>;
140
+ }
141
+ export interface QueueOptions {
142
+ readonly store: JobStore;
143
+ readonly clock: Clock;
144
+ }
145
+ export interface DeadJob {
146
+ readonly jobId: string;
147
+ readonly name: string;
148
+ readonly payload: string;
149
+ readonly attempts: number;
150
+ readonly reason: DeadReason;
151
+ readonly detail: string;
152
+ readonly enqueuedAt: Date;
153
+ readonly deadAt: Date;
154
+ }
155
+ export interface WorkerOptions<M> {
156
+ readonly handlers: readonly AnyJobHandler<M>[];
157
+ readonly store: JobStore;
158
+ readonly clock: Clock;
159
+ readonly concurrency: number;
160
+ readonly graceMs: number;
161
+ readonly leaseMs: number;
162
+ readonly onDead: (job: DeadJob) => void | Promise<void>;
163
+ readonly onHandlerError: (ctx: JobContext, error: unknown) => void;
164
+ readonly timeoutMs?: number;
165
+ readonly retries?: RetryPolicy;
166
+ readonly batch?: number;
167
+ readonly idleMs?: number;
168
+ readonly maxIdleMs?: number;
169
+ }
170
+ export interface Worker {
171
+ runOnce(): Promise<RunReport>;
172
+ start(): void;
173
+ onShutdown(options?: {
174
+ readonly graceMs: number;
175
+ }): Promise<void>;
176
+ listDead(opts: {
177
+ readonly limit: number;
178
+ readonly reason?: DeadReason;
179
+ }): Promise<readonly DeadJob[]>;
180
+ replay(jobId: string): Promise<boolean>;
181
+ }
182
+ export interface RunReport {
183
+ readonly claimed: number;
184
+ readonly done: number;
185
+ readonly retried: number;
186
+ readonly dead: number;
187
+ readonly skipped: number;
188
+ }
189
+ export declare function createQueue<M>(opts: QueueOptions): Queue<M>;
190
+ export declare function createWorker<M>(opts: WorkerOptions<M>): Worker;
191
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/queues/index.ts"],"names":[],"mappings":"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"}