@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/worker.js DELETED
@@ -1,273 +0,0 @@
1
- // The `worker` role: per-queue pools, a claim loop, lease heartbeats, and a graceful drain on
2
- // SIGTERM (stop claiming -> finish in-flight -> close). A worker that exits mid-job is not a
3
- // bug here — the visibility timeout re-delivers it — but a worker that exits mid-job on EVERY
4
- // deploy turns "at least once" into "always twice", so draining is on by default.
5
- import { logger, onShutdown, uuid, withSpan } from '@ultimat3/core';
6
- import { nowMs } from './clock';
7
- import { DEFAULT_QUEUE, DEFAULT_VISIBILITY_TIMEOUT_MS } from './driver';
8
- import { JobTimeoutError } from './errors';
9
- import { eventBus } from './events';
10
- import { getJob } from './job';
11
- import { createLimiter } from './limits';
12
- import { nextRetry } from './retry';
13
- import { createStepRunner, isStepSuspension } from './steps';
14
- /**
15
- * Run one claimed job to completion, suspension or failure, and settle it with the driver.
16
- * Shared by the worker loop and `x jobs run` so both take exactly the same code path.
17
- */
18
- export async function executeJob(options) {
19
- const { driver, claimed, handle } = options;
20
- const startedAt = nowMs(options.clock);
21
- const runner = createStepRunner({
22
- runId: claimed.runId,
23
- jobName: handle.name,
24
- store: driver.steps,
25
- ...(options.clock === undefined ? {} : { clock: options.clock }),
26
- events: options.events ?? eventBus(),
27
- });
28
- const settle = async (outcome) => {
29
- const steps = await driver.steps.list(claimed.runId);
30
- return { ...outcome, steps, replayed: runner.replayedNames() };
31
- };
32
- try {
33
- const input = handle.parse(claimed.input);
34
- const work = handle.run({
35
- input,
36
- step: runner.step,
37
- ctx: options.ctx,
38
- attempt: claimed.attempt,
39
- jobId: claimed.id,
40
- runId: claimed.runId,
41
- });
42
- await (handle.timeoutMs === undefined
43
- ? work
44
- : raceTimeout(work, handle.timeoutMs, handle.name));
45
- await driver.ack(claimed.id);
46
- return settle({
47
- outcome: 'completed',
48
- jobId: claimed.id,
49
- job: handle.name,
50
- attempt: claimed.attempt,
51
- durationMs: nowMs(options.clock) - startedAt,
52
- steps: [],
53
- replayed: [],
54
- });
55
- }
56
- catch (error) {
57
- if (isStepSuspension(error)) {
58
- const delayMs = Math.max(0, error.resumeAt - nowMs(options.clock));
59
- // countsAsAttempt: false — parking a run is not a failure.
60
- await driver.nack(claimed.id, { delayMs, countsAsAttempt: false });
61
- return settle({
62
- outcome: 'suspended',
63
- jobId: claimed.id,
64
- job: handle.name,
65
- attempt: claimed.attempt,
66
- durationMs: nowMs(options.clock) - startedAt,
67
- resumeAt: error.resumeAt,
68
- steps: [],
69
- replayed: [],
70
- });
71
- }
72
- const message = error instanceof Error ? error.message : String(error);
73
- const decision = nextRetry(handle.retry, claimed.attempt);
74
- await driver.nack(claimed.id, {
75
- delayMs: decision.delayMs,
76
- error: message,
77
- countsAsAttempt: true,
78
- deadLetter: !decision.retry && decision.deadLetter,
79
- });
80
- logger.warn('jobs.attempt.failed', {
81
- job: handle.name,
82
- jobId: claimed.id,
83
- attempt: claimed.attempt,
84
- retry: decision.retry,
85
- error: message,
86
- });
87
- return settle({
88
- outcome: decision.retry ? 'retried' : 'dead-lettered',
89
- jobId: claimed.id,
90
- job: handle.name,
91
- attempt: claimed.attempt,
92
- durationMs: nowMs(options.clock) - startedAt,
93
- error: message,
94
- steps: [],
95
- replayed: [],
96
- });
97
- }
98
- }
99
- function raceTimeout(work, timeoutMs, job) {
100
- return new Promise((resolve, reject) => {
101
- const timer = setTimeout(() => reject(new JobTimeoutError({ job, timeoutMs })), timeoutMs);
102
- work.then((value) => {
103
- clearTimeout(timer);
104
- resolve(value);
105
- }, (error) => {
106
- clearTimeout(timer);
107
- reject(error);
108
- });
109
- });
110
- }
111
- export function createWorker(options) {
112
- const workerId = options.workerId ?? `worker-${uuid()}`;
113
- const queues = options.queues ?? [DEFAULT_QUEUE];
114
- const visibilityTimeoutMs = options.visibilityTimeoutMs ?? DEFAULT_VISIBILITY_TIMEOUT_MS;
115
- const pollIntervalMs = options.pollIntervalMs ?? 250;
116
- const heartbeatIntervalMs = options.heartbeatIntervalMs ?? Math.floor(visibilityTimeoutMs / 3);
117
- const slotsFor = (queue) => typeof options.concurrency === 'number'
118
- ? options.concurrency
119
- : (options.concurrency?.[queue] ?? 5);
120
- const limiter = options.limiter ?? createLimiter({});
121
- const inFlight = new Set();
122
- let state = 'idle';
123
- let loop;
124
- let processed = 0;
125
- let failed = 0;
126
- let suspended = 0;
127
- let deadLettered = 0;
128
- const runClaimed = async (claimed) => {
129
- const handle = getJob(claimed.name);
130
- if (handle === undefined) {
131
- // Unknown job name: almost always a deploy skew. Park it, do not burn attempts.
132
- await options.driver.nack(claimed.id, {
133
- delayMs: 30_000,
134
- error: `no job registered as "${claimed.name}"`,
135
- countsAsAttempt: false,
136
- });
137
- return {
138
- outcome: 'suspended',
139
- jobId: claimed.id,
140
- job: claimed.name,
141
- attempt: claimed.attempt,
142
- durationMs: 0,
143
- error: `no job registered as "${claimed.name}"`,
144
- steps: [],
145
- replayed: [],
146
- };
147
- }
148
- const heartbeat = setInterval(() => {
149
- void options.driver.heartbeat(claimed.id, { visibilityTimeoutMs }).catch(() => undefined);
150
- }, heartbeatIntervalMs);
151
- try {
152
- return await withSpan(`job.${handle.name}`, () => executeJob({
153
- driver: options.driver,
154
- claimed,
155
- handle,
156
- ctx: options.context(),
157
- ...(options.clock === undefined ? {} : { clock: options.clock }),
158
- ...(options.events === undefined ? {} : { events: options.events }),
159
- }));
160
- }
161
- finally {
162
- clearInterval(heartbeat);
163
- }
164
- };
165
- const tick = async () => {
166
- if (state === 'draining' || state === 'stopped')
167
- return [];
168
- const results = [];
169
- for (const queue of queues) {
170
- const free = Math.max(0, slotsFor(queue) - limiter.inFlight({ queue }));
171
- if (free === 0)
172
- continue;
173
- const claimed = await options.driver.claim({
174
- queues: [queue],
175
- limit: free,
176
- visibilityTimeoutMs,
177
- workerId,
178
- });
179
- for (const job of claimed) {
180
- const lease = limiter.tryAcquire({
181
- queue,
182
- ...(job.tenantId === undefined ? {} : { tenantId: job.tenantId }),
183
- });
184
- if (lease === undefined) {
185
- // Over a tenant/queue/global cap: hand it straight back for another worker.
186
- await options.driver.nack(job.id, {
187
- delayMs: pollIntervalMs,
188
- countsAsAttempt: false,
189
- error: `limited: ${limiter.blockedBy({ queue, ...(job.tenantId === undefined ? {} : { tenantId: job.tenantId }) }) ?? 'unknown'}`,
190
- });
191
- continue;
192
- }
193
- const running = runClaimed(job)
194
- .then((execution) => {
195
- results.push(execution);
196
- if (execution.outcome === 'completed')
197
- processed += 1;
198
- else if (execution.outcome === 'suspended')
199
- suspended += 1;
200
- else if (execution.outcome === 'retried')
201
- failed += 1;
202
- else
203
- deadLettered += 1;
204
- return execution;
205
- })
206
- .finally(() => {
207
- lease.release();
208
- });
209
- inFlight.add(running);
210
- void running.finally(() => inFlight.delete(running));
211
- }
212
- }
213
- await Promise.allSettled([...inFlight]);
214
- return results;
215
- };
216
- const schedule = () => {
217
- loop = setTimeout(() => {
218
- void tick()
219
- .catch((error) => {
220
- logger.error('jobs.worker.tick-failed', {
221
- workerId,
222
- error: error instanceof Error ? error.message : String(error),
223
- });
224
- })
225
- .finally(() => {
226
- if (state === 'running')
227
- schedule();
228
- });
229
- }, pollIntervalMs);
230
- };
231
- const stop = async (reason = 'stop') => {
232
- if (state === 'stopped')
233
- return;
234
- state = 'draining';
235
- if (loop !== undefined)
236
- clearTimeout(loop);
237
- loop = undefined;
238
- logger.info('jobs.worker.draining', { workerId, reason, inFlight: inFlight.size });
239
- // Stop claiming, finish what we hold, then close. Anything else re-runs work on deploy.
240
- await Promise.allSettled([...inFlight]);
241
- await options.driver.close?.();
242
- state = 'stopped';
243
- };
244
- return {
245
- start() {
246
- if (state === 'running')
247
- return;
248
- state = 'running';
249
- logger.info('jobs.worker.started', { workerId, queues });
250
- // 'accept' phase: stop claiming before core waits on in-flight jobs.
251
- if (options.drainOnShutdown !== false) {
252
- onShutdown(`jobs.worker.${workerId}`, () => stop('SIGTERM'), { phase: 'accept' });
253
- }
254
- schedule();
255
- },
256
- tick,
257
- stop,
258
- async stats() {
259
- return {
260
- workerId,
261
- queues,
262
- state,
263
- inFlight: inFlight.size,
264
- processed,
265
- failed,
266
- suspended,
267
- deadLettered,
268
- queueDepth: [...(await options.driver.stats())],
269
- };
270
- },
271
- };
272
- }
273
- //# sourceMappingURL=worker.js.map
package/src/worker.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"worker.js","sourceRoot":"","sources":["worker.ts"],"names":[],"mappings":"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"}