@ultimat3/jobs 1.0.0 → 1.2.0

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.
Files changed (74) hide show
  1. package/package.json +5 -5
  2. package/src/worker.ts +33 -1
  3. package/src/clock.d.ts +0 -7
  4. package/src/clock.d.ts.map +0 -1
  5. package/src/clock.js +0 -21
  6. package/src/clock.js.map +0 -1
  7. package/src/driver-memory.d.ts +0 -9
  8. package/src/driver-memory.d.ts.map +0 -1
  9. package/src/driver-memory.js +0 -189
  10. package/src/driver-memory.js.map +0 -1
  11. package/src/driver-nats.d.ts +0 -7
  12. package/src/driver-nats.d.ts.map +0 -1
  13. package/src/driver-nats.js +0 -51
  14. package/src/driver-nats.js.map +0 -1
  15. package/src/driver-pg-sql.d.ts +0 -19
  16. package/src/driver-pg-sql.d.ts.map +0 -1
  17. package/src/driver-pg-sql.js +0 -160
  18. package/src/driver-pg-sql.js.map +0 -1
  19. package/src/driver-pg.d.ts +0 -17
  20. package/src/driver-pg.d.ts.map +0 -1
  21. package/src/driver-pg.js +0 -246
  22. package/src/driver-pg.js.map +0 -1
  23. package/src/driver-redis.d.ts +0 -7
  24. package/src/driver-redis.d.ts.map +0 -1
  25. package/src/driver-redis.js +0 -54
  26. package/src/driver-redis.js.map +0 -1
  27. package/src/driver.d.ts +0 -114
  28. package/src/driver.d.ts.map +0 -1
  29. package/src/driver.js +0 -14
  30. package/src/driver.js.map +0 -1
  31. package/src/errors.d.ts +0 -63
  32. package/src/errors.d.ts.map +0 -1
  33. package/src/errors.js +0 -105
  34. package/src/errors.js.map +0 -1
  35. package/src/events.d.ts +0 -35
  36. package/src/events.d.ts.map +0 -1
  37. package/src/events.js +0 -92
  38. package/src/events.js.map +0 -1
  39. package/src/index.d.ts +0 -32
  40. package/src/index.d.ts.map +0 -1
  41. package/src/index.js +0 -18
  42. package/src/index.js.map +0 -1
  43. package/src/inspect.d.ts +0 -82
  44. package/src/inspect.d.ts.map +0 -1
  45. package/src/inspect.js +0 -113
  46. package/src/inspect.js.map +0 -1
  47. package/src/job.d.ts +0 -71
  48. package/src/job.d.ts.map +0 -1
  49. package/src/job.js +0 -99
  50. package/src/job.js.map +0 -1
  51. package/src/limits.d.ts +0 -47
  52. package/src/limits.d.ts.map +0 -1
  53. package/src/limits.js +0 -0
  54. package/src/limits.js.map +0 -1
  55. package/src/outbox.d.ts +0 -81
  56. package/src/outbox.d.ts.map +0 -1
  57. package/src/outbox.js +0 -202
  58. package/src/outbox.js.map +0 -1
  59. package/src/retry.d.ts +0 -40
  60. package/src/retry.d.ts.map +0 -1
  61. package/src/retry.js +0 -59
  62. package/src/retry.js.map +0 -1
  63. package/src/scheduler.d.ts +0 -79
  64. package/src/scheduler.d.ts.map +0 -1
  65. package/src/scheduler.js +0 -183
  66. package/src/scheduler.js.map +0 -1
  67. package/src/steps.d.ts +0 -86
  68. package/src/steps.d.ts.map +0 -1
  69. package/src/steps.js +0 -227
  70. package/src/steps.js.map +0 -1
  71. package/src/worker.d.ts +0 -68
  72. package/src/worker.d.ts.map +0 -1
  73. package/src/worker.js +0 -273
  74. package/src/worker.js.map +0 -1
package/src/driver-pg.js DELETED
@@ -1,246 +0,0 @@
1
- // The DEFAULT driver: a Postgres queue. Zero infra to start — the database you already have
2
- // is the queue. `SELECT ... FOR UPDATE SKIP LOCKED` lets N workers claim disjoint batches
3
- // without a coordinator, and the visibility timeout (`visible_at`) makes a worker crash cost
4
- // one lease instead of one job. The statements themselves live in `driver-pg-sql.ts`.
5
- import { systemClock, uuid } from '@ultimat3/core';
6
- import { nowMs } from './clock';
7
- import { DEFAULT_QUEUE } from './driver';
8
- import { SQL_ACK, SQL_ADVISORY_UNLOCK, SQL_CLAIM, SQL_ENQUEUE, SQL_FIND_LIVE_BY_KEY, SQL_HEARTBEAT, SQL_NACK, SQL_STATS, SQL_STEP_GET, SQL_STEP_PUT, SQL_TRY_ADVISORY_LOCK, } from './driver-pg-sql';
9
- import { DriverUnavailableError, JobDuplicateError } from './errors';
10
- const num = (value) => value === null || value === undefined ? 0 : Number(value);
11
- const optionalNum = (value) => value === null || value === undefined ? undefined : Number(value);
12
- function toJobRecord(row) {
13
- const visibleAt = optionalNum(row.visible_at);
14
- return {
15
- id: row.id,
16
- name: row.name,
17
- queue: row.queue,
18
- input: row.input,
19
- idempotencyKey: row.idempotency_key,
20
- runId: row.run_id,
21
- attempt: row.attempt,
22
- maxAttempts: row.max_attempts,
23
- state: row.state,
24
- runAt: num(row.run_at),
25
- createdAt: num(row.created_at),
26
- updatedAt: num(row.updated_at),
27
- ...(row.tenant_id === null ? {} : { tenantId: row.tenant_id }),
28
- ...(row.last_error === null ? {} : { lastError: row.last_error }),
29
- ...(row.claimed_by === null ? {} : { claimedBy: row.claimed_by }),
30
- ...(visibleAt === undefined ? {} : { visibleAt }),
31
- };
32
- }
33
- function toStepRecord(row) {
34
- const completedAt = optionalNum(row.completed_at);
35
- const wakeAt = optionalNum(row.wake_at);
36
- return {
37
- runId: row.run_id,
38
- name: row.name,
39
- status: row.status,
40
- output: row.output,
41
- startedAt: num(row.started_at),
42
- attempts: row.attempts,
43
- ...(completedAt === undefined ? {} : { completedAt }),
44
- ...(wakeAt === undefined ? {} : { wakeAt }),
45
- ...(row.event === null ? {} : { event: row.event }),
46
- ...(row.correlation_key === null ? {} : { correlationKey: row.correlation_key }),
47
- ...(row.error === null ? {} : { error: row.error }),
48
- };
49
- }
50
- function resolveExecutor(injected) {
51
- if (injected !== undefined)
52
- return injected;
53
- throw new DriverUnavailableError({
54
- driver: 'pg',
55
- cause: 'no PgExecutor was provided and Bun.sql is not configured',
56
- fix: 'set DATABASE_URL in .env then run `x db up`, or use driver: "memory" in app.config.ts',
57
- });
58
- }
59
- function pgStepStore(exec) {
60
- return {
61
- async get(runId, name) {
62
- const rows = await exec().query(SQL_STEP_GET, [runId, name]);
63
- const row = rows[0];
64
- return row === undefined ? undefined : toStepRecord(row);
65
- },
66
- async put(record) {
67
- await exec().query(SQL_STEP_PUT, [
68
- record.runId,
69
- record.name,
70
- record.status,
71
- JSON.stringify(record.output ?? null),
72
- record.startedAt,
73
- record.completedAt ?? null,
74
- record.wakeAt ?? null,
75
- record.event ?? null,
76
- record.correlationKey ?? null,
77
- record.attempts,
78
- record.error ?? null,
79
- ]);
80
- },
81
- async list(runId) {
82
- const rows = await exec().query(`select * from x_job_steps where run_id = $1 order by started_at`, [runId]);
83
- return rows.map(toStepRecord);
84
- },
85
- async del(runId, name) {
86
- await exec().query(`delete from x_job_steps where run_id = $1 and name = $2`, [runId, name]);
87
- },
88
- async clear(runId) {
89
- await exec().query(`delete from x_job_steps where run_id = $1`, [runId]);
90
- },
91
- };
92
- }
93
- export function createPgDriver(options = {}) {
94
- const clock = options.clock ?? systemClock;
95
- let executor;
96
- const exec = () => {
97
- executor ??= resolveExecutor(options.executor);
98
- return executor;
99
- };
100
- const introspect = {
101
- async job(jobId) {
102
- const rows = await exec().query(`select * from x_jobs where id = $1`, [jobId]);
103
- const row = rows[0];
104
- return row === undefined ? undefined : toJobRecord(row);
105
- },
106
- async list(filter = {}) {
107
- const rows = await exec().query(`select * from x_jobs
108
- where ($1::text is null or queue = $1)
109
- and ($2::text is null or name = $2)
110
- and ($3::text is null or state = $3)
111
- order by created_at desc
112
- limit $4`, [filter.queue ?? null, filter.name ?? null, filter.state ?? null, filter.limit ?? 100]);
113
- return rows.map(toJobRecord);
114
- },
115
- async deadLetters(limit = 100) {
116
- const rows = await exec().query(`select * from x_jobs where state = 'dead' order by updated_at desc limit $1`, [limit]);
117
- return rows.map(toJobRecord);
118
- },
119
- async requeue(jobId, requeueOptions) {
120
- if (requeueOptions?.fromStep !== undefined) {
121
- const current = await this.job(jobId);
122
- if (current !== undefined) {
123
- await exec().query(`delete from x_job_steps where run_id = $1 and name = $2`, [
124
- current.runId,
125
- requeueOptions.fromStep,
126
- ]);
127
- }
128
- }
129
- const rows = await exec().query(`update x_jobs set state = 'ready', attempt = 0, run_at = now(), updated_at = now()
130
- where id = $1 returning *`, [jobId]);
131
- const row = rows[0];
132
- if (row === undefined) {
133
- throw new DriverUnavailableError({
134
- driver: 'pg',
135
- cause: `job ${jobId} does not exist`,
136
- fix: 'x jobs list --state dead --json',
137
- });
138
- }
139
- return toJobRecord(row);
140
- },
141
- };
142
- return {
143
- name: 'pg',
144
- steps: pgStepStore(exec),
145
- introspect,
146
- async enqueue(request) {
147
- const runAt = request.runAt ?? nowMs(clock);
148
- const rows = await exec().query(SQL_ENQUEUE, [
149
- uuid(),
150
- request.name,
151
- request.queue || DEFAULT_QUEUE,
152
- JSON.stringify(request.input ?? null),
153
- request.idempotencyKey,
154
- request.runId ?? uuid(),
155
- request.maxAttempts,
156
- runAt,
157
- request.tenantId ?? null,
158
- ]);
159
- const inserted = rows[0];
160
- if (inserted !== undefined) {
161
- return { id: inserted.id, runId: inserted.run_id, deduped: false };
162
- }
163
- // `do nothing` fired: a live job already owns this idempotency key.
164
- const existing = await exec().query(SQL_FIND_LIVE_BY_KEY, [
165
- request.idempotencyKey,
166
- ]);
167
- const found = existing[0];
168
- if (found === undefined) {
169
- throw new DriverUnavailableError({
170
- driver: 'pg',
171
- cause: `enqueue of "${request.name}" was rejected but no live row holds its idempotency key`,
172
- fix: 'x db check — the x_jobs_idempotency_live_idx index is missing or stale',
173
- });
174
- }
175
- if (request.onConflict === 'error') {
176
- throw new JobDuplicateError({
177
- job: request.name,
178
- idempotencyKey: request.idempotencyKey,
179
- existingId: found.id,
180
- });
181
- }
182
- return { id: found.id, runId: found.run_id, deduped: true };
183
- },
184
- async claim(claimOptions) {
185
- const queues = claimOptions.queues.length > 0 ? claimOptions.queues : [DEFAULT_QUEUE];
186
- const rows = await exec().query(SQL_CLAIM, [
187
- queues,
188
- claimOptions.limit,
189
- claimOptions.workerId,
190
- claimOptions.visibilityTimeoutMs,
191
- ]);
192
- const at = nowMs(clock);
193
- return rows.map((row) => {
194
- const record = toJobRecord(row);
195
- return {
196
- ...record,
197
- claimedAt: at,
198
- visibleAt: record.visibleAt ?? at + claimOptions.visibilityTimeoutMs,
199
- };
200
- });
201
- },
202
- async ack(jobId) {
203
- await exec().query(SQL_ACK, [jobId]);
204
- },
205
- async nack(jobId, nackOptions) {
206
- const counts = nackOptions.countsAsAttempt !== false;
207
- const state = nackOptions.deadLetter === true ? 'dead' : counts ? 'ready' : 'suspended';
208
- await exec().query(SQL_NACK, [
209
- jobId,
210
- state,
211
- counts,
212
- nackOptions.delayMs,
213
- nackOptions.error ?? null,
214
- ]);
215
- },
216
- async heartbeat(jobId, heartbeatOptions) {
217
- await exec().query(SQL_HEARTBEAT, [jobId, heartbeatOptions.visibilityTimeoutMs]);
218
- },
219
- async stats() {
220
- const rows = await exec().query(SQL_STATS, []);
221
- return rows.map((row) => ({
222
- queue: row.queue,
223
- ready: num(row.ready),
224
- delayed: num(row.delayed),
225
- running: num(row.running),
226
- suspended: num(row.suspended),
227
- dead: num(row.dead),
228
- oldestReadyMs: Math.round(num(row.oldest_ready_ms)),
229
- }));
230
- },
231
- };
232
- }
233
- /** Advisory-lock leader election, used by the `scheduler` role. */
234
- export function createPgLeader(lockKey, options = {}) {
235
- const exec = () => resolveExecutor(options.executor);
236
- return {
237
- async acquire() {
238
- const rows = await exec().query(SQL_TRY_ADVISORY_LOCK, [lockKey]);
239
- return rows[0]?.locked === true;
240
- },
241
- async release() {
242
- await exec().query(SQL_ADVISORY_UNLOCK, [lockKey]);
243
- },
244
- };
245
- }
246
- //# sourceMappingURL=driver-pg.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"driver-pg.js","sourceRoot":"","sources":["driver-pg.ts"],"names":[],"mappings":"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"}
@@ -1,7 +0,0 @@
1
- import type { JobDriver } from './driver';
2
- export interface RedisDriverOptions {
3
- readonly url?: string;
4
- readonly consumerGroup?: string;
5
- }
6
- export declare function createRedisDriver(_options?: RedisDriverOptions): JobDriver;
7
- //# sourceMappingURL=driver-redis.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"driver-redis.d.ts","sourceRoot":"","sources":["driver-redis.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAKV,SAAS,EAGV,MAAM,UAAU,CAAC;AA4BlB,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,GAAE,kBAAuB,GAAG,SAAS,CAuB9E"}
@@ -1,54 +0,0 @@
1
- // Redis driver — interface-complete, not implemented. Honest stub: correct types so an app
2
- // can be written against it and `x verify` typechecks, with one labelled throw per method so
3
- // nobody discovers the gap from a silently-dropped job.
4
- //
5
- // Design it will implement when written: a per-queue Redis Stream with a consumer group
6
- // (XADD / XREADGROUP / XACK), `XAUTOCLAIM` for the visibility timeout, a ZSET for delayed
7
- // and suspended runs, and step records in a hash keyed by run id.
8
- import { JobsNotImplementedError } from './errors';
9
- const FIX = 'use driver: "pg" (default) or "memory" — see docs/jobs/drivers.md#redis';
10
- const unavailable = (method) => {
11
- throw new JobsNotImplementedError({ feature: `redis jobs driver (${method})`, fix: FIX });
12
- };
13
- const redisStepStore = () => ({
14
- get(_runId, _name) {
15
- return unavailable('steps.get');
16
- },
17
- put(_record) {
18
- return unavailable('steps.put');
19
- },
20
- list(_runId) {
21
- return unavailable('steps.list');
22
- },
23
- del(_runId, _name) {
24
- return unavailable('steps.del');
25
- },
26
- clear(_runId) {
27
- return unavailable('steps.clear');
28
- },
29
- });
30
- export function createRedisDriver(_options = {}) {
31
- return {
32
- name: 'redis',
33
- steps: redisStepStore(),
34
- enqueue(_request) {
35
- return unavailable('enqueue');
36
- },
37
- claim(_options) {
38
- return unavailable('claim');
39
- },
40
- ack(_jobId) {
41
- return unavailable('ack');
42
- },
43
- nack(_jobId, _options) {
44
- return unavailable('nack');
45
- },
46
- heartbeat(_jobId, _options) {
47
- return unavailable('heartbeat');
48
- },
49
- stats() {
50
- return unavailable('stats');
51
- },
52
- };
53
- }
54
- //# sourceMappingURL=driver-redis.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"driver-redis.js","sourceRoot":"","sources":["driver-redis.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,6FAA6F;AAC7F,wDAAwD;AACxD,EAAE;AACF,wFAAwF;AACxF,0FAA0F;AAC1F,kEAAkE;AAWlE,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAGnD,MAAM,GAAG,GAAG,yEAAyE,CAAC;AAEtF,MAAM,WAAW,GAAG,CAAC,MAAc,EAAS,EAAE;IAC5C,MAAM,IAAI,uBAAuB,CAAC,EAAE,OAAO,EAAE,sBAAsB,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;AAC5F,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,GAAc,EAAE,CAAC,CAAC;IACvC,GAAG,CAAC,MAAc,EAAE,KAAa;QAC/B,OAAO,WAAW,CAAC,WAAW,CAAC,CAAC;IAClC,CAAC;IACD,GAAG,CAAC,OAAmB;QACrB,OAAO,WAAW,CAAC,WAAW,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,CAAC,MAAc;QACjB,OAAO,WAAW,CAAC,YAAY,CAAC,CAAC;IACnC,CAAC;IACD,GAAG,CAAC,MAAc,EAAE,KAAa;QAC/B,OAAO,WAAW,CAAC,WAAW,CAAC,CAAC;IAClC,CAAC;IACD,KAAK,CAAC,MAAc;QAClB,OAAO,WAAW,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC;CACF,CAAC,CAAC;AAOH,MAAM,UAAU,iBAAiB,CAAC,QAAQ,GAAuB,EAAE;IACjE,OAAO;QACL,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,cAAc,EAAE;QACvB,OAAO,CAAC,QAAwB;YAC9B,OAAO,WAAW,CAAC,SAAS,CAAC,CAAC;QAChC,CAAC;QACD,KAAK,CAAC,QAAsB;YAC1B,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QACD,GAAG,CAAC,MAAc;YAChB,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,CAAC,MAAc,EAAE,QAAqB;YACxC,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;QACD,SAAS,CAAC,MAAc,EAAE,QAAkD;YAC1E,OAAO,WAAW,CAAC,WAAW,CAAC,CAAC;QAClC,CAAC;QACD,KAAK;YACH,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;KACF,CAAC;AACJ,CAAC"}
package/src/driver.d.ts DELETED
@@ -1,114 +0,0 @@
1
- import type { StepStore } from './steps';
2
- export type JobState = 'ready' | 'delayed' | 'running' | 'suspended' | 'done' | 'failed' | 'dead';
3
- export interface JobRecord {
4
- readonly id: string;
5
- readonly name: string;
6
- readonly queue: string;
7
- readonly input: unknown;
8
- /** Dedupe key from the job definition. At-least-once delivery leans on this. */
9
- readonly idempotencyKey: string;
10
- /** Stable across retries and suspensions — the key every step record hangs off. */
11
- readonly runId: string;
12
- readonly attempt: number;
13
- readonly maxAttempts: number;
14
- readonly state: JobState;
15
- /** Epoch ms; the job is invisible until then. */
16
- readonly runAt: number;
17
- readonly createdAt: number;
18
- readonly updatedAt: number;
19
- /** Actor's orgId, for per-tenant limits. */
20
- readonly tenantId?: string;
21
- readonly lastError?: string;
22
- readonly claimedBy?: string;
23
- readonly visibleAt?: number;
24
- }
25
- export type ConflictPolicy = 'dedupe' | 'error';
26
- export interface EnqueueRequest {
27
- readonly name: string;
28
- readonly queue: string;
29
- readonly input: unknown;
30
- readonly idempotencyKey: string;
31
- readonly maxAttempts: number;
32
- /** Epoch ms. Omit for "now". */
33
- readonly runAt?: number;
34
- readonly tenantId?: string;
35
- /** Reuse an existing run id when resuming, so step history is preserved. */
36
- readonly runId?: string;
37
- readonly onConflict?: ConflictPolicy;
38
- }
39
- export interface EnqueueResult {
40
- readonly id: string;
41
- readonly runId: string;
42
- /** True when an in-flight job already held this idempotency key. */
43
- readonly deduped: boolean;
44
- }
45
- export interface ClaimOptions {
46
- readonly queues: readonly string[];
47
- readonly limit: number;
48
- /** Lease length. A worker that dies without ack makes the job claimable again after this. */
49
- readonly visibilityTimeoutMs: number;
50
- readonly workerId: string;
51
- }
52
- export interface ClaimedJob extends JobRecord {
53
- readonly claimedAt: number;
54
- readonly visibleAt: number;
55
- }
56
- export interface NackOptions {
57
- /** Delay before the job becomes claimable again. */
58
- readonly delayMs: number;
59
- readonly error?: string;
60
- /**
61
- * False for a suspension (`step.sleep`): parking a run is not a failure and must not burn
62
- * a retry attempt, or a 3-day sleep would dead-letter the job.
63
- */
64
- readonly countsAsAttempt?: boolean;
65
- readonly deadLetter?: boolean;
66
- }
67
- export interface QueueStats {
68
- readonly queue: string;
69
- readonly ready: number;
70
- readonly delayed: number;
71
- readonly running: number;
72
- readonly suspended: number;
73
- readonly dead: number;
74
- /** Age in ms of the oldest claimable job — the number that decides autoscaling. */
75
- readonly oldestReadyMs: number;
76
- }
77
- export interface JobFilter {
78
- readonly queue?: string;
79
- readonly name?: string;
80
- readonly state?: JobState;
81
- readonly limit?: number;
82
- }
83
- /** Optional: powers `/_x` and the MCP tools. A minimal driver may omit it. */
84
- export interface JobIntrospection {
85
- job(jobId: string): Promise<JobRecord | undefined>;
86
- list(filter?: JobFilter): Promise<readonly JobRecord[]>;
87
- deadLetters(limit?: number): Promise<readonly JobRecord[]>;
88
- /** Re-queue a dead/failed job. `fromStep` drops step records from that step onward. */
89
- requeue(jobId: string, options?: {
90
- readonly fromStep?: string;
91
- }): Promise<JobRecord>;
92
- }
93
- export interface JobDriver {
94
- readonly name: string;
95
- /** Step persistence lives with the queue: one store, one transaction boundary. */
96
- readonly steps: StepStore;
97
- enqueue(request: EnqueueRequest): Promise<EnqueueResult>;
98
- claim(options: ClaimOptions): Promise<readonly ClaimedJob[]>;
99
- ack(jobId: string): Promise<void>;
100
- nack(jobId: string, options: NackOptions): Promise<void>;
101
- /** Extends the lease of a long-running job so it is not double-claimed. */
102
- heartbeat(jobId: string, options: {
103
- readonly visibilityTimeoutMs: number;
104
- }): Promise<void>;
105
- stats(): Promise<readonly QueueStats[]>;
106
- readonly introspect?: JobIntrospection;
107
- close?(): Promise<void>;
108
- }
109
- export declare const DEFAULT_QUEUE = "default";
110
- export declare const DEFAULT_VISIBILITY_TIMEOUT_MS = 30000;
111
- /** Set once at boot from `app.config.ts`. Roles share one driver instance per process. */
112
- export declare function setJobDriver(driver: JobDriver): void;
113
- export declare function jobDriver(): JobDriver | undefined;
114
- //# sourceMappingURL=driver.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["driver.ts"],"names":[],"mappings":"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"}
package/src/driver.js DELETED
@@ -1,14 +0,0 @@
1
- // The queue contract. Every driver (pg, memory, redis, nats) implements exactly this, so
2
- // switching backends is a config line and ZERO job-code change. Six methods and no more:
3
- // claim/ack/nack with a visibility timeout is the smallest set that survives a worker crash.
4
- export const DEFAULT_QUEUE = 'default';
5
- export const DEFAULT_VISIBILITY_TIMEOUT_MS = 30_000;
6
- let ambient;
7
- /** Set once at boot from `app.config.ts`. Roles share one driver instance per process. */
8
- export function setJobDriver(driver) {
9
- ambient = driver;
10
- }
11
- export function jobDriver() {
12
- return ambient;
13
- }
14
- //# sourceMappingURL=driver.js.map
package/src/driver.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"driver.js","sourceRoot":"","sources":["driver.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,yFAAyF;AACzF,6FAA6F;AAuH7F,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC;AACvC,MAAM,CAAC,MAAM,6BAA6B,GAAG,MAAM,CAAC;AAEpD,IAAI,OAA8B,CAAC;AAEnC,0FAA0F;AAC1F,MAAM,UAAU,YAAY,CAAC,MAAiB;IAC5C,OAAO,GAAG,MAAM,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/src/errors.d.ts DELETED
@@ -1,63 +0,0 @@
1
- import { UltimateError } from '@ultimat3/core';
2
- export declare const JOB_ERROR_CODES: readonly ['X_JOB_DUPLICATE', 'X_STEP_DUPLICATE', 'X_JOB_TIMEOUT', 'X_JOB_MAX_ATTEMPTS', 'X_DRIVER_UNAVAILABLE', 'X_IDEMPOTENCY_REQUIRED', 'X_OUTBOX_NO_TX', 'X_NOT_IMPLEMENTED'];
3
- export type JobErrorCode = (typeof JOB_ERROR_CODES)[number];
4
- /** An enqueue collided with a live job holding the same idempotency key under `onConflict: 'error'`. */
5
- export declare class JobDuplicateError extends UltimateError {
6
- constructor(input: {
7
- job: string;
8
- idempotencyKey: string;
9
- existingId: string;
10
- });
11
- }
12
- /** Two steps in one run share a name, so replay cannot tell their persisted results apart. */
13
- export declare class StepDuplicateError extends UltimateError {
14
- constructor(input: {
15
- job: string;
16
- step: string;
17
- });
18
- }
19
- export declare class JobTimeoutError extends UltimateError {
20
- constructor(input: {
21
- job: string;
22
- timeoutMs: number;
23
- step?: string;
24
- });
25
- }
26
- /** Retries exhausted. The job is in the dead-letter queue, not lost. */
27
- export declare class JobMaxAttemptsError extends UltimateError {
28
- constructor(input: {
29
- job: string;
30
- jobId: string;
31
- attempts: number;
32
- lastError: string;
33
- });
34
- }
35
- export declare class DriverUnavailableError extends UltimateError {
36
- constructor(input: {
37
- driver: string;
38
- cause: string;
39
- fix: string;
40
- });
41
- }
42
- /**
43
- * The type signature already requires `idempotencyKey`; this is the runtime backstop for
44
- * generated code and JS callers, so the guarantee holds at both ends.
45
- */
46
- export declare class IdempotencyRequiredError extends UltimateError {
47
- constructor(input: {
48
- job: string;
49
- });
50
- }
51
- /** An outbox enqueue happened with no ambient transaction to join. */
52
- export declare class OutboxNoTxError extends UltimateError {
53
- constructor(input: {
54
- job: string;
55
- });
56
- }
57
- export declare class JobsNotImplementedError extends UltimateError {
58
- constructor(input: {
59
- feature: string;
60
- fix: string;
61
- });
62
- }
63
- //# sourceMappingURL=errors.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["errors.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,eAAO,MAAM,eAAe,YAC1B,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,wBAAwB,EACxB,gBAAgB,EAChB,mBAAmB,CACX,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAI5D,wGAAwG;AACxG,qBAAa,iBAAkB,SAAQ,aAAa;IAClD,YAAY,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAO7E;CACF;AAED,8FAA8F;AAC9F,qBAAa,kBAAmB,SAAQ,aAAa;IACnD,YAAY,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAO/C;CACF;AAED,qBAAa,eAAgB,SAAQ,aAAa;IAChD,YAAY,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAUnE;CACF;AAED,wEAAwE;AACxE,qBAAa,mBAAoB,SAAQ,aAAa;IACpD,YAAY,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,EAOrF;CACF;AAED,qBAAa,sBAAuB,SAAQ,aAAa;IACvD,YAAY,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAOhE;CACF;AAED;;;GAGG;AACH,qBAAa,wBAAyB,SAAQ,aAAa;IACzD,YAAY,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,EAOjC;CACF;AAED,sEAAsE;AACtE,qBAAa,eAAgB,SAAQ,aAAa;IAChD,YAAY,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,EAOjC;CACF;AAED,qBAAa,uBAAwB,SAAQ,aAAa;IACxD,YAAY,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAOlD;CACF"}
package/src/errors.js DELETED
@@ -1,105 +0,0 @@
1
- // The X_* codes owned by @ultimat3/jobs. Every one names the command or code change that
2
- // fixes it — a job failure an agent cannot act on is a job failure that gets retried forever.
3
- import { UltimateError } from '@ultimat3/core';
4
- export const JOB_ERROR_CODES = [
5
- 'X_JOB_DUPLICATE',
6
- 'X_STEP_DUPLICATE',
7
- 'X_JOB_TIMEOUT',
8
- 'X_JOB_MAX_ATTEMPTS',
9
- 'X_DRIVER_UNAVAILABLE',
10
- 'X_IDEMPOTENCY_REQUIRED',
11
- 'X_OUTBOX_NO_TX',
12
- 'X_NOT_IMPLEMENTED',
13
- ];
14
- const docsFor = (code) => `https://ultimate.dev/errors/${code}`;
15
- /** An enqueue collided with a live job holding the same idempotency key under `onConflict: 'error'`. */
16
- export class JobDuplicateError extends UltimateError {
17
- constructor(input) {
18
- super({
19
- code: 'X_JOB_DUPLICATE',
20
- cause: `job "${input.job}" already queued as ${input.existingId} with idempotencyKey "${input.idempotencyKey}"`,
21
- fix: 'pass onConflict: "dedupe" to enqueue, or make idempotencyKey narrower',
22
- docs: docsFor('X_JOB_DUPLICATE'),
23
- });
24
- }
25
- }
26
- /** Two steps in one run share a name, so replay cannot tell their persisted results apart. */
27
- export class StepDuplicateError extends UltimateError {
28
- constructor(input) {
29
- super({
30
- code: 'X_STEP_DUPLICATE',
31
- cause: `job "${input.job}" used step name "${input.step}" twice in one run`,
32
- fix: `rename one of them, e.g. step.run('${input.step}-2', ...) — step names are the replay key`,
33
- docs: docsFor('X_STEP_DUPLICATE'),
34
- });
35
- }
36
- }
37
- export class JobTimeoutError extends UltimateError {
38
- constructor(input) {
39
- super({
40
- code: 'X_JOB_TIMEOUT',
41
- cause: input.step === undefined
42
- ? `job "${input.job}" exceeded its ${input.timeoutMs}ms timeout`
43
- : `job "${input.job}" step "${input.step}" exceeded its ${input.timeoutMs}ms timeout`,
44
- fix: `raise timeout on the job definition, or split the work into step.run() calls`,
45
- docs: docsFor('X_JOB_TIMEOUT'),
46
- });
47
- }
48
- }
49
- /** Retries exhausted. The job is in the dead-letter queue, not lost. */
50
- export class JobMaxAttemptsError extends UltimateError {
51
- constructor(input) {
52
- super({
53
- code: 'X_JOB_MAX_ATTEMPTS',
54
- cause: `job "${input.job}" failed ${input.attempts} times, last error: ${input.lastError}`,
55
- fix: `x jobs retry ${input.jobId}`,
56
- docs: docsFor('X_JOB_MAX_ATTEMPTS'),
57
- });
58
- }
59
- }
60
- export class DriverUnavailableError extends UltimateError {
61
- constructor(input) {
62
- super({
63
- code: 'X_DRIVER_UNAVAILABLE',
64
- cause: `jobs driver "${input.driver}" is unavailable: ${input.cause}`,
65
- fix: input.fix,
66
- docs: docsFor('X_DRIVER_UNAVAILABLE'),
67
- });
68
- }
69
- }
70
- /**
71
- * The type signature already requires `idempotencyKey`; this is the runtime backstop for
72
- * generated code and JS callers, so the guarantee holds at both ends.
73
- */
74
- export class IdempotencyRequiredError extends UltimateError {
75
- constructor(input) {
76
- super({
77
- code: 'X_IDEMPOTENCY_REQUIRED',
78
- cause: `job "${input.job}" has no idempotencyKey — at-least-once delivery would run it twice`,
79
- fix: `add idempotencyKey: (input) => \`${input.job}:\${input.id}\` to the job definition`,
80
- docs: docsFor('X_IDEMPOTENCY_REQUIRED'),
81
- });
82
- }
83
- }
84
- /** An outbox enqueue happened with no ambient transaction to join. */
85
- export class OutboxNoTxError extends UltimateError {
86
- constructor(input) {
87
- super({
88
- code: 'X_OUTBOX_NO_TX',
89
- cause: `ctx.jobs.enqueue(${input.job}) ran outside a transaction with outbox: 'required'`,
90
- fix: 'wrap the call in ctx.tx(async (tx) => ...), or enqueue with { outbox: false }',
91
- docs: docsFor('X_OUTBOX_NO_TX'),
92
- });
93
- }
94
- }
95
- export class JobsNotImplementedError extends UltimateError {
96
- constructor(input) {
97
- super({
98
- code: 'X_NOT_IMPLEMENTED',
99
- cause: `${input.feature} is declared but not implemented in @ultimat3/jobs`,
100
- fix: input.fix,
101
- docs: docsFor('X_NOT_IMPLEMENTED'),
102
- });
103
- }
104
- }
105
- //# sourceMappingURL=errors.js.map
package/src/errors.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["errors.ts"],"names":[],"mappings":"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"}