@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/scheduler.js DELETED
@@ -1,183 +0,0 @@
1
- // The `task` primitive + the `scheduler` role. A task NEVER does work: it enqueues jobs, so
2
- // retries, idempotency and observability all come from the job machinery instead of being
3
- // re-invented per cron.
4
- //
5
- // `tz` is required by the type. A cron without a timezone is a bug waiting for March: `0 3 *
6
- // * *` in a DST-observing zone runs twice or zero times on the switch day, and "the nightly
7
- // digest went out at 2am and again at 3am" is not a mystery anyone should have to debug.
8
- //
9
- // Exactly one node dispatches per tick, enforced by a Postgres advisory lock. Two schedulers
10
- // double-enqueue every task; the idempotency key would absorb it, but leader election means
11
- // the queue never sees the duplicate at all.
12
- import { assert, logger } from '@ultimat3/core';
13
- import { instant, nextCronOccurrence } from '@ultimat3/time';
14
- import { nowMs } from './clock';
15
- const defaultCronResolver = (cron, options) =>
16
- // Instant is a branded Date, so it satisfies CronResolver's Date return directly.
17
- nextCronOccurrence(cron, options.tz, instant(options.from));
18
- const registry = new Map();
19
- let anonymous = 0;
20
- export function task(definition) {
21
- anonymous += 1;
22
- const name = definition.name ?? `anonymous-task-${anonymous}`;
23
- // Runtime backstop; the type already makes an omitted tz a build error.
24
- assert(typeof definition.tz === 'string' && definition.tz.length > 0, `task "${name}" needs an explicit IANA tz — a cron without a timezone is a bug`, `add tz to task("${name}"), e.g. tz: 'UTC' — an unzoned cron silently drifts by an hour at every DST transition`);
25
- const handle = {
26
- kind: 'task',
27
- name,
28
- cron: definition.cron,
29
- tz: definition.tz,
30
- catchUp: definition.catchUp ?? 'skip',
31
- maxCatchUp: definition.maxCatchUp ?? 10,
32
- entries: () => definition.enqueue(),
33
- };
34
- registry.set(name, handle);
35
- return handle;
36
- }
37
- export function nameTasks(record) {
38
- for (const [exportName, handle] of Object.entries(record)) {
39
- if (handle.name === exportName)
40
- continue;
41
- registry.delete(handle.name);
42
- Object.defineProperty(handle, 'name', { value: exportName, configurable: true });
43
- registry.set(exportName, handle);
44
- }
45
- }
46
- export function registeredTasks() {
47
- return [...registry.values()].sort((a, b) => a.name.localeCompare(b.name));
48
- }
49
- export function getTask(name) {
50
- return registry.get(name);
51
- }
52
- export function resetTasks() {
53
- registry.clear();
54
- anonymous = 0;
55
- }
56
- /** Single-node default: always the leader. Multi-node uses `createPgLeader()`. */
57
- export function soleLeader() {
58
- return {
59
- acquire: () => Promise.resolve(true),
60
- release: () => Promise.resolve(),
61
- };
62
- }
63
- export function createMemorySchedulerState() {
64
- const fired = new Map();
65
- return {
66
- lastFiredAt: (taskName) => Promise.resolve(fired.get(taskName)),
67
- markFired(taskName, occurrenceMs) {
68
- fired.set(taskName, occurrenceMs);
69
- return Promise.resolve();
70
- },
71
- };
72
- }
73
- export function createScheduler(options) {
74
- const state = options.state ?? createMemorySchedulerState();
75
- const resolveCron = options.cron ?? defaultCronResolver;
76
- const tickIntervalMs = options.tickIntervalMs ?? 1_000;
77
- const leader = options.leader ?? soleLeader();
78
- let timer;
79
- let isLeader = false;
80
- const nextRunFor = (handle, from) => resolveCron(handle.cron, { tz: handle.tz, from: from ?? new Date(nowMs(options.clock)) });
81
- /**
82
- * Occurrences in `(after, until]`. Walking forward from the last fire is what makes
83
- * catch-up possible at all — a scheduler that only knows "now" cannot know what it missed.
84
- */
85
- const occurrencesSince = (handle, after, until) => {
86
- const out = [];
87
- let cursor = after;
88
- for (let i = 0; i < handle.maxCatchUp; i += 1) {
89
- const next = nextRunFor(handle, new Date(cursor)).getTime();
90
- if (!Number.isFinite(next) || next <= cursor || next > until)
91
- break;
92
- out.push(next);
93
- cursor = next;
94
- }
95
- return out;
96
- };
97
- const dispatch = async (handle, occurrenceMs, catchUp) => {
98
- const jobs = [];
99
- for (const [handleForJob, input] of handle.entries()) {
100
- const result = await options.driver.enqueue({
101
- name: handleForJob.name,
102
- queue: handleForJob.queue,
103
- input,
104
- // Occurrence-scoped key: two schedulers, or a retried tick, cannot double-fire.
105
- idempotencyKey: `${handle.name}:${occurrenceMs}:${handleForJob.idempotencyKeyFor(input)}`,
106
- maxAttempts: handleForJob.retry.attempts,
107
- runAt: occurrenceMs,
108
- });
109
- jobs.push({ job: handleForJob.name, result });
110
- }
111
- await state.markFired(handle.name, occurrenceMs);
112
- logger.info('jobs.scheduler.dispatched', {
113
- task: handle.name,
114
- occurrence: new Date(occurrenceMs).toISOString(),
115
- tz: handle.tz,
116
- catchUp,
117
- jobs: jobs.length,
118
- });
119
- return { task: handle.name, occurrenceMs, jobs, catchUp };
120
- };
121
- const tick = async () => {
122
- if (!isLeader) {
123
- isLeader = await leader.acquire();
124
- if (!isLeader)
125
- return [];
126
- }
127
- const at = nowMs(options.clock);
128
- const tasks = options.tasks ?? registeredTasks();
129
- const dispatched = [];
130
- for (const handle of tasks) {
131
- const last = await state.lastFiredAt(handle.name);
132
- if (last === undefined) {
133
- // First sight of this task: arm it, never fire retroactively for all of history.
134
- await state.markFired(handle.name, nextRunFor(handle, new Date(at)).getTime() - 1);
135
- continue;
136
- }
137
- const due = occurrencesSince(handle, last, at);
138
- if (due.length === 0)
139
- continue;
140
- if (handle.catchUp === 'skip') {
141
- const latest = due[due.length - 1];
142
- if (latest !== undefined)
143
- dispatched.push(await dispatch(handle, latest, due.length > 1));
144
- continue;
145
- }
146
- if (handle.catchUp === 'run-once') {
147
- const first = due[0];
148
- if (first !== undefined)
149
- dispatched.push(await dispatch(handle, first, due.length > 1));
150
- continue;
151
- }
152
- for (const occurrence of due) {
153
- dispatched.push(await dispatch(handle, occurrence, occurrence !== due[due.length - 1]));
154
- }
155
- }
156
- return dispatched;
157
- };
158
- return {
159
- start() {
160
- if (timer !== undefined)
161
- return;
162
- timer = setInterval(() => {
163
- void tick().catch((error) => {
164
- logger.error('jobs.scheduler.tick-failed', {
165
- error: error instanceof Error ? error.message : String(error),
166
- });
167
- });
168
- }, tickIntervalMs);
169
- logger.info('jobs.scheduler.started', { tasks: (options.tasks ?? registeredTasks()).length });
170
- },
171
- async stop() {
172
- if (timer !== undefined)
173
- clearInterval(timer);
174
- timer = undefined;
175
- if (isLeader)
176
- await leader.release();
177
- isLeader = false;
178
- },
179
- tick,
180
- nextRunFor,
181
- };
182
- }
183
- //# sourceMappingURL=scheduler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["scheduler.ts"],"names":[],"mappings":"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"}
package/src/steps.d.ts DELETED
@@ -1,86 +0,0 @@
1
- import type { Clock } from '@ultimat3/core';
2
- import type { DurationInput } from './clock';
3
- export type StepStatus = 'completed' | 'sleeping' | 'waiting' | 'failed';
4
- export interface StepRecord {
5
- readonly runId: string;
6
- readonly name: string;
7
- readonly status: StepStatus;
8
- /** The memoized return value. Present only when `status === 'completed'`. */
9
- readonly output?: unknown;
10
- readonly startedAt: number;
11
- readonly completedAt?: number;
12
- /** Epoch ms at which a sleeping/waiting step becomes runnable. */
13
- readonly wakeAt?: number;
14
- readonly event?: string;
15
- readonly correlationKey?: string;
16
- readonly attempts: number;
17
- readonly error?: string;
18
- }
19
- export interface StepStore {
20
- get(runId: string, name: string): Promise<StepRecord | undefined>;
21
- put(record: StepRecord): Promise<void>;
22
- list(runId: string): Promise<readonly StepRecord[]>;
23
- del(runId: string, name: string): Promise<void>;
24
- clear(runId: string): Promise<void>;
25
- }
26
- /** The slice of the event bus a waiting step needs. Implemented by `events.ts`. */
27
- export interface EventLookup {
28
- find(event: string, correlationKey: string | undefined, afterMs: number): Promise<{
29
- readonly payload: unknown;
30
- readonly publishedAt: number;
31
- } | undefined>;
32
- }
33
- export interface WaitForEventOptions {
34
- /** How long to wait before giving up. Default 24h. */
35
- readonly timeout?: DurationInput;
36
- /** Correlation key the published event must carry — usually an entity id. */
37
- readonly match?: string;
38
- /** Default false: a timeout resolves `undefined`. `true` fails the job with X_JOB_TIMEOUT. */
39
- readonly required?: boolean;
40
- }
41
- export interface StepApi {
42
- /** Run once, ever. On replay the persisted output is returned and `fn` is not called. */
43
- run<T>(name: string, fn: () => Promise<T> | T): Promise<T>;
44
- /** Suspend the run. `sleep(duration)` derives the step name from the duration. */
45
- sleep(name: string, duration: DurationInput): Promise<void>;
46
- sleep(duration: DurationInput): Promise<void>;
47
- waitForEvent<T>(name: string, event: string, options?: WaitForEventOptions): Promise<T | undefined>;
48
- }
49
- /**
50
- * Control flow, not a failure: it must never be logged as an error or counted as an attempt.
51
- * Branded by string rather than `instanceof` so two copies of this module still agree.
52
- */
53
- export declare class StepSuspension extends Error {
54
- static readonly brand = "ultimate.jobs.suspension";
55
- readonly brand: string;
56
- readonly step: string;
57
- readonly resumeAt: number;
58
- readonly reason: 'sleep' | 'event';
59
- constructor(input: {
60
- step: string;
61
- resumeAt: number;
62
- reason: 'sleep' | 'event';
63
- });
64
- }
65
- export declare function isStepSuspension(error: unknown): error is StepSuspension;
66
- export declare function createMemoryStepStore(): StepStore;
67
- export interface StepRunnerOptions {
68
- readonly runId: string;
69
- readonly jobName: string;
70
- readonly store: StepStore;
71
- readonly clock?: Clock;
72
- readonly events?: EventLookup;
73
- /** How long a waiting step stays parked between event polls. Default 30s. */
74
- readonly eventPollMs?: number;
75
- /** Per-step ceiling; the job-level timeout is enforced by the worker. */
76
- readonly stepTimeoutMs?: number;
77
- }
78
- export interface StepRunner {
79
- readonly step: StepApi;
80
- /** Names used in THIS attempt, in order — the trace shown by `x jobs show`. */
81
- usedNames(): readonly string[];
82
- /** Names that were served from storage instead of executed. */
83
- replayedNames(): readonly string[];
84
- }
85
- export declare function createStepRunner(options: StepRunnerOptions): StepRunner;
86
- //# sourceMappingURL=steps.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"steps.d.ts","sourceRoot":"","sources":["steps.ts"],"names":[],"mappings":"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"}
package/src/steps.js DELETED
@@ -1,227 +0,0 @@
1
- // Durable steps — the heart of the package. Each step's result is PERSISTED before the next
2
- // one starts, so a retry replays completed steps from storage instead of re-executing them:
3
- // the welcome email is not sent twice because step 3 failed. That makes step names the replay
4
- // key, which is why they must be deterministic and unique within a run (X_STEP_DUPLICATE).
5
- //
6
- // Suspension (sleep / waitForEvent) unwinds the run by throwing a StepSuspension. The worker
7
- // catches it and re-queues the job for `resumeAt` instead of holding a process for three days.
8
- import { logger } from '@ultimat3/core';
9
- import { nowMs, toMs } from './clock';
10
- import { JobTimeoutError, StepDuplicateError } from './errors';
11
- /**
12
- * Control flow, not a failure: it must never be logged as an error or counted as an attempt.
13
- * Branded by string rather than `instanceof` so two copies of this module still agree.
14
- */
15
- export class StepSuspension extends Error {
16
- static brand = 'ultimate.jobs.suspension';
17
- brand = StepSuspension.brand;
18
- step;
19
- resumeAt;
20
- reason;
21
- constructor(input) {
22
- super(`step "${input.step}" suspended until ${new Date(input.resumeAt).toISOString()}`);
23
- this.name = 'StepSuspension';
24
- this.step = input.step;
25
- this.resumeAt = input.resumeAt;
26
- this.reason = input.reason;
27
- }
28
- }
29
- export function isStepSuspension(error) {
30
- return error instanceof Error && error.brand === StepSuspension.brand;
31
- }
32
- export function createMemoryStepStore() {
33
- const byRun = new Map();
34
- const runOf = (runId) => {
35
- let run = byRun.get(runId);
36
- if (run === undefined) {
37
- run = new Map();
38
- byRun.set(runId, run);
39
- }
40
- return run;
41
- };
42
- return {
43
- get(runId, name) {
44
- return Promise.resolve(byRun.get(runId)?.get(name));
45
- },
46
- put(record) {
47
- runOf(record.runId).set(record.name, record);
48
- return Promise.resolve();
49
- },
50
- list(runId) {
51
- const records = [...(byRun.get(runId)?.values() ?? [])];
52
- return Promise.resolve(records.sort((a, b) => a.startedAt - b.startedAt));
53
- },
54
- del(runId, name) {
55
- byRun.get(runId)?.delete(name);
56
- return Promise.resolve();
57
- },
58
- clear(runId) {
59
- byRun.delete(runId);
60
- return Promise.resolve();
61
- },
62
- };
63
- }
64
- export function createStepRunner(options) {
65
- const { runId, jobName, store } = options;
66
- const used = [];
67
- const replayed = [];
68
- const clock = options.clock;
69
- const pollMs = options.eventPollMs ?? 30_000;
70
- const claimName = (name) => {
71
- if (used.includes(name))
72
- throw new StepDuplicateError({ job: jobName, step: name });
73
- used.push(name);
74
- };
75
- const now = () => nowMs(clock);
76
- async function run(name, fn) {
77
- claimName(name);
78
- const existing = await store.get(runId, name);
79
- if (existing?.status === 'completed') {
80
- replayed.push(name);
81
- return existing.output;
82
- }
83
- const startedAt = existing?.startedAt ?? now();
84
- const attempts = (existing?.attempts ?? 0) + 1;
85
- try {
86
- const output = await withStepTimeout(fn(), options.stepTimeoutMs, () => new JobTimeoutError({ job: jobName, step: name, timeoutMs: options.stepTimeoutMs ?? 0 }));
87
- // Persist BEFORE returning: a crash one line later must not re-run this step.
88
- await store.put({
89
- runId,
90
- name,
91
- status: 'completed',
92
- output,
93
- startedAt,
94
- completedAt: now(),
95
- attempts,
96
- });
97
- return output;
98
- }
99
- catch (error) {
100
- if (isStepSuspension(error))
101
- throw error;
102
- await store.put({
103
- runId,
104
- name,
105
- status: 'failed',
106
- startedAt,
107
- attempts,
108
- error: error instanceof Error ? error.message : String(error),
109
- });
110
- throw error;
111
- }
112
- }
113
- async function sleep(a, b) {
114
- // `sleep('3d')` — the duration doubles as the step name, which stays deterministic.
115
- const name = b === undefined ? `sleep:${String(a)}` : String(a);
116
- const duration = b === undefined ? a : b;
117
- claimName(name);
118
- const existing = await store.get(runId, name);
119
- if (existing?.status === 'completed') {
120
- replayed.push(name);
121
- return;
122
- }
123
- const at = now();
124
- if (existing?.status === 'sleeping' && existing.wakeAt !== undefined) {
125
- if (existing.wakeAt <= at) {
126
- await store.put({ ...existing, status: 'completed', completedAt: at });
127
- return;
128
- }
129
- throw new StepSuspension({ step: name, resumeAt: existing.wakeAt, reason: 'sleep' });
130
- }
131
- const wakeAt = at + toMs(duration);
132
- await store.put({
133
- runId,
134
- name,
135
- status: 'sleeping',
136
- startedAt: at,
137
- wakeAt,
138
- attempts: 1,
139
- });
140
- throw new StepSuspension({ step: name, resumeAt: wakeAt, reason: 'sleep' });
141
- }
142
- async function waitForEvent(name, event, waitOptions = {}) {
143
- claimName(name);
144
- const existing = await store.get(runId, name);
145
- if (existing?.status === 'completed') {
146
- replayed.push(name);
147
- return existing.output;
148
- }
149
- const at = now();
150
- const startedAt = existing?.startedAt ?? at;
151
- const deadline = startedAt + toMs(waitOptions.timeout ?? 86_400_000);
152
- const correlationKey = waitOptions.match;
153
- const hit = await options.events?.find(event, correlationKey, startedAt);
154
- if (hit !== undefined) {
155
- await store.put({
156
- runId,
157
- name,
158
- status: 'completed',
159
- output: hit.payload,
160
- startedAt,
161
- completedAt: at,
162
- event,
163
- attempts: (existing?.attempts ?? 0) + 1,
164
- ...(correlationKey === undefined ? {} : { correlationKey }),
165
- });
166
- return hit.payload;
167
- }
168
- if (at >= deadline) {
169
- if (waitOptions.required === true) {
170
- throw new JobTimeoutError({
171
- job: jobName,
172
- step: name,
173
- timeoutMs: toMs(waitOptions.timeout ?? 86_400_000),
174
- });
175
- }
176
- logger.warn('jobs.step.wait-timeout', { job: jobName, step: name, event });
177
- await store.put({
178
- runId,
179
- name,
180
- status: 'completed',
181
- output: undefined,
182
- startedAt,
183
- completedAt: at,
184
- event,
185
- attempts: (existing?.attempts ?? 0) + 1,
186
- });
187
- return undefined;
188
- }
189
- const resumeAt = Math.min(deadline, at + pollMs);
190
- await store.put({
191
- runId,
192
- name,
193
- status: 'waiting',
194
- startedAt,
195
- wakeAt: resumeAt,
196
- event,
197
- attempts: (existing?.attempts ?? 0) + 1,
198
- ...(correlationKey === undefined ? {} : { correlationKey }),
199
- });
200
- throw new StepSuspension({ step: name, resumeAt, reason: 'event' });
201
- }
202
- const step = {
203
- run,
204
- sleep: sleep,
205
- waitForEvent,
206
- };
207
- return {
208
- step,
209
- usedNames: () => [...used],
210
- replayedNames: () => [...replayed],
211
- };
212
- }
213
- function withStepTimeout(work, timeoutMs, error) {
214
- if (timeoutMs === undefined || timeoutMs <= 0)
215
- return Promise.resolve(work);
216
- return new Promise((resolve, reject) => {
217
- const timer = setTimeout(() => reject(error()), timeoutMs);
218
- Promise.resolve(work).then((value) => {
219
- clearTimeout(timer);
220
- resolve(value);
221
- }, (cause) => {
222
- clearTimeout(timer);
223
- reject(cause);
224
- });
225
- });
226
- }
227
- //# sourceMappingURL=steps.js.map
package/src/steps.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"steps.js","sourceRoot":"","sources":["steps.ts"],"names":[],"mappings":"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"}
package/src/worker.d.ts DELETED
@@ -1,68 +0,0 @@
1
- import type { Clock, Ctx } from '@ultimat3/core';
2
- import type { ClaimedJob, JobDriver, QueueStats } from './driver';
3
- import type { AnyJobHandle } from './job';
4
- import type { Limiter } from './limits';
5
- import type { EventLookup, StepRecord } from './steps';
6
- export type JobOutcome = 'completed' | 'suspended' | 'retried' | 'dead-lettered';
7
- export interface JobExecution {
8
- readonly outcome: JobOutcome;
9
- readonly jobId: string;
10
- readonly job: string;
11
- readonly attempt: number;
12
- readonly durationMs: number;
13
- readonly resumeAt?: number;
14
- readonly error?: string;
15
- readonly steps: readonly StepRecord[];
16
- readonly replayed: readonly string[];
17
- }
18
- export interface ExecuteJobOptions {
19
- readonly driver: JobDriver;
20
- readonly claimed: ClaimedJob;
21
- readonly handle: AnyJobHandle;
22
- readonly ctx: Ctx;
23
- readonly clock?: Clock;
24
- readonly events?: EventLookup;
25
- }
26
- /**
27
- * Run one claimed job to completion, suspension or failure, and settle it with the driver.
28
- * Shared by the worker loop and `x jobs run` so both take exactly the same code path.
29
- */
30
- export declare function executeJob(options: ExecuteJobOptions): Promise<JobExecution>;
31
- export interface WorkerOptions {
32
- readonly driver: JobDriver;
33
- /** Queues this process serves. Default `['default']`. */
34
- readonly queues?: readonly string[];
35
- /** Slots per queue. A number applies to every queue. */
36
- readonly concurrency?: number | Readonly<Record<string, number>>;
37
- readonly limiter?: Limiter;
38
- readonly clock?: Clock;
39
- readonly events?: EventLookup;
40
- /** Supplies the ambient Ctx for a job run; the app wires ALS + tenant here. */
41
- readonly context: () => Ctx;
42
- readonly visibilityTimeoutMs?: number;
43
- readonly pollIntervalMs?: number;
44
- readonly heartbeatIntervalMs?: number;
45
- readonly workerId?: string;
46
- /** Default true. Registers a SIGTERM drain via `onShutdown`. */
47
- readonly drainOnShutdown?: boolean;
48
- }
49
- export interface WorkerStats {
50
- readonly workerId: string;
51
- readonly queues: readonly string[];
52
- readonly state: 'idle' | 'running' | 'draining' | 'stopped';
53
- readonly inFlight: number;
54
- readonly processed: number;
55
- readonly failed: number;
56
- readonly suspended: number;
57
- readonly deadLettered: number;
58
- readonly queueDepth: readonly QueueStats[];
59
- }
60
- export interface Worker {
61
- start(): void;
62
- /** One claim+run round. Returns jobs processed. Tests drive this instead of the timer. */
63
- tick(): Promise<readonly JobExecution[]>;
64
- stop(reason?: string): Promise<void>;
65
- stats(): Promise<WorkerStats>;
66
- }
67
- export declare function createWorker(options: WorkerOptions): Worker;
68
- //# sourceMappingURL=worker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["worker.ts"],"names":[],"mappings":"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"}