@platformatic/job-queue 0.0.1 → 0.1.0-alpha.3

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 (58) hide show
  1. package/README.md +511 -0
  2. package/dist/consumer.d.ts +43 -0
  3. package/dist/consumer.d.ts.map +1 -0
  4. package/dist/consumer.js +214 -0
  5. package/dist/consumer.js.map +1 -0
  6. package/dist/errors.d.ts +60 -0
  7. package/dist/errors.d.ts.map +1 -0
  8. package/dist/errors.js +141 -0
  9. package/dist/errors.js.map +1 -0
  10. package/dist/index.d.ts +12 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +13 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/producer.d.ts +39 -0
  15. package/dist/producer.d.ts.map +1 -0
  16. package/dist/producer.js +163 -0
  17. package/dist/producer.js.map +1 -0
  18. package/dist/queue.d.ts +42 -0
  19. package/dist/queue.d.ts.map +1 -0
  20. package/dist/queue.js +153 -0
  21. package/dist/queue.js.map +1 -0
  22. package/dist/reaper.d.ts +52 -0
  23. package/dist/reaper.d.ts.map +1 -0
  24. package/dist/reaper.js +376 -0
  25. package/dist/reaper.js.map +1 -0
  26. package/dist/serde/index.d.ts +19 -0
  27. package/dist/serde/index.d.ts.map +1 -0
  28. package/dist/serde/index.js +18 -0
  29. package/dist/serde/index.js.map +1 -0
  30. package/dist/storage/file.d.ts +44 -0
  31. package/dist/storage/file.d.ts.map +1 -0
  32. package/dist/storage/file.js +601 -0
  33. package/dist/storage/file.js.map +1 -0
  34. package/dist/storage/memory.d.ts +39 -0
  35. package/dist/storage/memory.d.ts.map +1 -0
  36. package/dist/storage/memory.js +292 -0
  37. package/dist/storage/memory.js.map +1 -0
  38. package/dist/storage/redis.d.ts +47 -0
  39. package/dist/storage/redis.d.ts.map +1 -0
  40. package/dist/storage/redis.js +317 -0
  41. package/dist/storage/redis.js.map +1 -0
  42. package/dist/storage/types.d.ts +179 -0
  43. package/dist/storage/types.d.ts.map +1 -0
  44. package/dist/storage/types.js +2 -0
  45. package/dist/storage/types.js.map +1 -0
  46. package/dist/types.d.ts +126 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +2 -0
  49. package/dist/types.js.map +1 -0
  50. package/dist/utils/id.d.ts +10 -0
  51. package/dist/utils/id.d.ts.map +1 -0
  52. package/dist/utils/id.js +18 -0
  53. package/dist/utils/id.js.map +1 -0
  54. package/dist/utils/state.d.ts +13 -0
  55. package/dist/utils/state.d.ts.map +1 -0
  56. package/dist/utils/state.js +22 -0
  57. package/dist/utils/state.js.map +1 -0
  58. package/package.json +45 -9
package/dist/reaper.js ADDED
@@ -0,0 +1,376 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { createJsonSerde } from "./serde/index.js";
4
+ import { parseState } from "./utils/state.js";
5
+ const LOCK_KEY = 'reaper:lock';
6
+ const DEFAULT_LOCK_TTL = 30000;
7
+ const DEFAULT_RENEWAL_INTERVAL = 10000;
8
+ const DEFAULT_ACQUIRE_RETRY_INTERVAL = 5000;
9
+ /**
10
+ * Reaper monitors for stalled jobs and requeues them.
11
+ *
12
+ * A job is considered stalled if it has been in "processing" state
13
+ * longer than the visibility timeout.
14
+ *
15
+ * When leader election is enabled, multiple Reaper instances can run
16
+ * for high availability, with only one active at a time.
17
+ */
18
+ export class Reaper extends EventEmitter {
19
+ #storage;
20
+ #payloadSerde;
21
+ #visibilityTimeout;
22
+ #leaderElection;
23
+ #running = false;
24
+ #unsubscribe = null;
25
+ #processingTimers = new Map();
26
+ // Leader election state
27
+ #reaperId;
28
+ #isLeader = false;
29
+ #leadershipTimer = null;
30
+ constructor(config) {
31
+ super();
32
+ this.#storage = config.storage;
33
+ this.#payloadSerde = config.payloadSerde ?? createJsonSerde();
34
+ this.#visibilityTimeout = config.visibilityTimeout ?? 30000;
35
+ this.#leaderElection = config.leaderElection ?? { enabled: false };
36
+ this.#reaperId = randomUUID();
37
+ }
38
+ /**
39
+ * Get the unique identifier for this reaper instance
40
+ */
41
+ get reaperId() {
42
+ return this.#reaperId;
43
+ }
44
+ /**
45
+ * Check if this reaper is currently the leader
46
+ */
47
+ get isLeader() {
48
+ return this.#isLeader;
49
+ }
50
+ /**
51
+ * Start the reaper
52
+ */
53
+ async start() {
54
+ if (this.#running)
55
+ return;
56
+ this.#running = true;
57
+ if (this.#leaderElection.enabled) {
58
+ await this.#startLeadershipLoop();
59
+ }
60
+ else {
61
+ // No leader election, become active immediately
62
+ await this.#becomeActive();
63
+ }
64
+ }
65
+ /**
66
+ * Stop the reaper gracefully
67
+ */
68
+ async stop() {
69
+ if (!this.#running)
70
+ return;
71
+ this.#running = false;
72
+ // Stop leadership loop
73
+ if (this.#leadershipTimer) {
74
+ clearInterval(this.#leadershipTimer);
75
+ this.#leadershipTimer = null;
76
+ }
77
+ // Release lock if we're leader
78
+ if (this.#isLeader && this.#leaderElection.enabled) {
79
+ await this.#releaseLeadership();
80
+ this.#isLeader = false;
81
+ }
82
+ // Become inactive (cleanup)
83
+ await this.#becomeInactive();
84
+ }
85
+ /**
86
+ * Become active: subscribe to events and do initial scan
87
+ */
88
+ async #becomeActive() {
89
+ // Subscribe to job events
90
+ this.#unsubscribe = await this.#storage.subscribeToEvents((id, event) => {
91
+ this.#handleEvent(id, event);
92
+ });
93
+ // Do an initial scan for any jobs that were processing before we started
94
+ await this.#checkStalledJobs();
95
+ }
96
+ /**
97
+ * Become inactive: clear timers and unsubscribe
98
+ */
99
+ async #becomeInactive() {
100
+ // Clear all processing timers
101
+ for (const timer of this.#processingTimers.values()) {
102
+ clearTimeout(timer);
103
+ }
104
+ this.#processingTimers.clear();
105
+ // Unsubscribe from events
106
+ if (this.#unsubscribe) {
107
+ await this.#unsubscribe();
108
+ this.#unsubscribe = null;
109
+ }
110
+ }
111
+ /**
112
+ * Start the leadership acquisition loop
113
+ */
114
+ async #startLeadershipLoop() {
115
+ const lockTTL = this.#leaderElection.lockTTL ?? DEFAULT_LOCK_TTL;
116
+ // Try to acquire lock immediately
117
+ const acquired = await this.#tryAcquireLock(lockTTL);
118
+ if (acquired) {
119
+ this.#isLeader = true;
120
+ await this.#becomeActive();
121
+ this.emit('leadershipAcquired');
122
+ }
123
+ // Start the appropriate timer based on current role
124
+ this.#scheduleLeadershipCheck();
125
+ }
126
+ /**
127
+ * Schedule the next leadership check (renewal or acquisition)
128
+ */
129
+ #scheduleLeadershipCheck() {
130
+ const lockTTL = this.#leaderElection.lockTTL ?? DEFAULT_LOCK_TTL;
131
+ const renewalInterval = this.#leaderElection.renewalInterval ?? DEFAULT_RENEWAL_INTERVAL;
132
+ const acquireRetryInterval = this.#leaderElection.acquireRetryInterval ?? DEFAULT_ACQUIRE_RETRY_INTERVAL;
133
+ // Clear any existing timer
134
+ if (this.#leadershipTimer) {
135
+ clearInterval(this.#leadershipTimer);
136
+ }
137
+ const interval = this.#isLeader ? renewalInterval : acquireRetryInterval;
138
+ this.#leadershipTimer = setInterval(async () => {
139
+ if (!this.#running)
140
+ return;
141
+ try {
142
+ if (this.#isLeader) {
143
+ // Renew lock
144
+ const renewed = await this.#tryRenewLock(lockTTL);
145
+ if (!renewed) {
146
+ // Lost leadership
147
+ await this.#transitionToFollower();
148
+ }
149
+ }
150
+ else {
151
+ // Try to acquire lock
152
+ const acquired = await this.#tryAcquireLock(lockTTL);
153
+ if (acquired) {
154
+ await this.#transitionToLeader();
155
+ }
156
+ }
157
+ }
158
+ catch (err) {
159
+ this.emit('error', err);
160
+ }
161
+ }, interval);
162
+ }
163
+ /**
164
+ * Try to acquire the leader lock
165
+ */
166
+ async #tryAcquireLock(ttlMs) {
167
+ if (!this.#storage.acquireLeaderLock) {
168
+ // Storage doesn't support leader election
169
+ this.emit('error', new Error('Storage does not support leader election'));
170
+ return false;
171
+ }
172
+ return this.#storage.acquireLeaderLock(LOCK_KEY, this.#reaperId, ttlMs);
173
+ }
174
+ /**
175
+ * Try to renew the leader lock
176
+ */
177
+ async #tryRenewLock(ttlMs) {
178
+ if (!this.#storage.renewLeaderLock) {
179
+ return false;
180
+ }
181
+ return this.#storage.renewLeaderLock(LOCK_KEY, this.#reaperId, ttlMs);
182
+ }
183
+ /**
184
+ * Release the leader lock
185
+ */
186
+ async #releaseLeadership() {
187
+ if (!this.#storage.releaseLeaderLock) {
188
+ return;
189
+ }
190
+ await this.#storage.releaseLeaderLock(LOCK_KEY, this.#reaperId);
191
+ }
192
+ /**
193
+ * Transition from follower to leader
194
+ */
195
+ async #transitionToLeader() {
196
+ this.#isLeader = true;
197
+ // Become active
198
+ await this.#becomeActive();
199
+ // Update interval timing (leaders use renewalInterval)
200
+ this.#scheduleLeadershipCheck();
201
+ this.emit('leadershipAcquired');
202
+ }
203
+ /**
204
+ * Transition from leader to follower
205
+ */
206
+ async #transitionToFollower() {
207
+ this.#isLeader = false;
208
+ // Become inactive
209
+ await this.#becomeInactive();
210
+ // Update interval timing (followers use acquireRetryInterval)
211
+ this.#scheduleLeadershipCheck();
212
+ this.emit('leadershipLost');
213
+ }
214
+ /**
215
+ * Handle a job state change event
216
+ */
217
+ #handleEvent(id, event) {
218
+ if (event === 'processing') {
219
+ // Start a timer for this job
220
+ this.#startTimer(id);
221
+ }
222
+ else if (event === 'completed' || event === 'failed' || event === 'cancelled') {
223
+ // Cancel any existing timer
224
+ this.#cancelTimer(id);
225
+ }
226
+ }
227
+ /**
228
+ * Start a visibility timeout timer for a job
229
+ */
230
+ #startTimer(id) {
231
+ // Cancel any existing timer first
232
+ this.#cancelTimer(id);
233
+ const timer = setTimeout(() => {
234
+ this.#processingTimers.delete(id);
235
+ this.#checkJob(id).catch((err) => {
236
+ this.emit('error', err);
237
+ });
238
+ }, this.#visibilityTimeout);
239
+ this.#processingTimers.set(id, timer);
240
+ }
241
+ /**
242
+ * Cancel the timer for a job
243
+ */
244
+ #cancelTimer(id) {
245
+ const timer = this.#processingTimers.get(id);
246
+ if (timer) {
247
+ clearTimeout(timer);
248
+ this.#processingTimers.delete(id);
249
+ }
250
+ }
251
+ /**
252
+ * Check if a job is stalled and requeue if necessary
253
+ */
254
+ async #checkJob(id) {
255
+ if (!this.#running)
256
+ return;
257
+ if (this.#leaderElection.enabled && !this.#isLeader)
258
+ return;
259
+ const state = await this.#storage.getJobState(id);
260
+ if (!state)
261
+ return;
262
+ const { status, timestamp, workerId } = parseState(state);
263
+ if (status !== 'processing') {
264
+ // Job is no longer processing, nothing to do
265
+ return;
266
+ }
267
+ // Check if visibility timeout has elapsed
268
+ const elapsed = Date.now() - timestamp;
269
+ if (elapsed < this.#visibilityTimeout) {
270
+ // Not yet stalled, restart timer for remaining time
271
+ const remaining = this.#visibilityTimeout - elapsed;
272
+ const timer = setTimeout(() => {
273
+ this.#processingTimers.delete(id);
274
+ this.#checkJob(id).catch((err) => {
275
+ this.emit('error', err);
276
+ });
277
+ }, remaining);
278
+ this.#processingTimers.set(id, timer);
279
+ return;
280
+ }
281
+ // Job is stalled - need to recover it
282
+ await this.#recoverStalledJob(id, workerId);
283
+ }
284
+ /**
285
+ * Recover a stalled job by requeueing it
286
+ */
287
+ async #recoverStalledJob(id, workerId) {
288
+ if (!workerId) {
289
+ this.emit('error', new Error(`Cannot recover stalled job ${id}: no workerId in state`));
290
+ return;
291
+ }
292
+ // Get the job from the worker's processing queue
293
+ const processingJobs = await this.#storage.getProcessingJobs(workerId);
294
+ // Find the message for this job
295
+ let jobMessage = null;
296
+ for (const message of processingJobs) {
297
+ try {
298
+ const queueMessage = this.#payloadSerde.deserialize(message);
299
+ if (queueMessage.id === id) {
300
+ jobMessage = message;
301
+ break;
302
+ }
303
+ }
304
+ catch {
305
+ // Ignore deserialization errors
306
+ }
307
+ }
308
+ if (!jobMessage) {
309
+ // Job not found in processing queue - it may have already been processed
310
+ // Clear the state to prevent future checks
311
+ return;
312
+ }
313
+ // Requeue the job
314
+ await this.#storage.requeue(id, jobMessage, workerId);
315
+ // Update state to reflect retry
316
+ const queueMessage = this.#payloadSerde.deserialize(jobMessage);
317
+ const newState = `failing:${Date.now()}:${queueMessage.attempts + 1}`;
318
+ await this.#storage.setJobState(id, newState);
319
+ // Emit stalled event
320
+ this.emit('stalled', id);
321
+ }
322
+ /**
323
+ * Periodically check all workers' processing queues for stalled jobs
324
+ */
325
+ async #checkStalledJobs() {
326
+ if (!this.#running)
327
+ return;
328
+ if (this.#leaderElection.enabled && !this.#isLeader)
329
+ return;
330
+ const workers = await this.#storage.getWorkers();
331
+ for (const workerId of workers) {
332
+ await this.#checkWorkerProcessingQueue(workerId);
333
+ }
334
+ }
335
+ /**
336
+ * Check a single worker's processing queue for stalled jobs
337
+ */
338
+ async #checkWorkerProcessingQueue(workerId) {
339
+ if (!this.#running)
340
+ return;
341
+ if (this.#leaderElection.enabled && !this.#isLeader)
342
+ return;
343
+ const processingJobs = await this.#storage.getProcessingJobs(workerId);
344
+ for (const message of processingJobs) {
345
+ try {
346
+ const queueMessage = this.#payloadSerde.deserialize(message);
347
+ const state = await this.#storage.getJobState(queueMessage.id);
348
+ if (!state)
349
+ continue;
350
+ const { status, timestamp } = parseState(state);
351
+ if (status === 'processing') {
352
+ const elapsed = Date.now() - timestamp;
353
+ if (elapsed >= this.#visibilityTimeout) {
354
+ // Job is stalled
355
+ await this.#recoverStalledJob(queueMessage.id, workerId);
356
+ }
357
+ else if (!this.#processingTimers.has(queueMessage.id)) {
358
+ // Start a timer for remaining time
359
+ const remaining = this.#visibilityTimeout - elapsed;
360
+ const timer = setTimeout(() => {
361
+ this.#processingTimers.delete(queueMessage.id);
362
+ this.#checkJob(queueMessage.id).catch((err) => {
363
+ this.emit('error', err);
364
+ });
365
+ }, remaining);
366
+ this.#processingTimers.set(queueMessage.id, timer);
367
+ }
368
+ }
369
+ }
370
+ catch {
371
+ // Ignore deserialization errors
372
+ }
373
+ }
374
+ }
375
+ }
376
+ //# sourceMappingURL=reaper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reaper.js","sourceRoot":"","sources":["../src/reaper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Serialization/deserialization interface for queue messages
3
+ */
4
+ export interface Serde<T> {
5
+ serialize(value: T): Buffer;
6
+ deserialize(buffer: Buffer): T;
7
+ }
8
+ /**
9
+ * JSON serializer - default implementation
10
+ */
11
+ export declare class JsonSerde<T> implements Serde<T> {
12
+ serialize(value: T): Buffer;
13
+ deserialize(buffer: Buffer): T;
14
+ }
15
+ /**
16
+ * Create a JSON serde instance
17
+ */
18
+ export declare function createJsonSerde<T>(): Serde<T>;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/serde/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC;IACtB,SAAS,CAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAA;IAC5B,WAAW,CAAE,MAAM,EAAE,MAAM,GAAG,CAAC,CAAA;CAChC;AAED;;GAEG;AACH,qBAAa,SAAS,CAAC,CAAC,CAAE,YAAW,KAAK,CAAC,CAAC,CAAC;IAC3C,SAAS,CAAE,KAAK,EAAE,CAAC,GAAG,MAAM;IAI5B,WAAW,CAAE,MAAM,EAAE,MAAM,GAAG,CAAC;CAGhC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,KAAM,KAAK,CAAC,CAAC,CAAC,CAE9C"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * JSON serializer - default implementation
3
+ */
4
+ export class JsonSerde {
5
+ serialize(value) {
6
+ return Buffer.from(JSON.stringify(value));
7
+ }
8
+ deserialize(buffer) {
9
+ return JSON.parse(buffer.toString());
10
+ }
11
+ }
12
+ /**
13
+ * Create a JSON serde instance
14
+ */
15
+ export function createJsonSerde() {
16
+ return new JsonSerde();
17
+ }
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/serde/index.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,MAAM,OAAO,SAAS;IACpB,SAAS,CAAE,KAAQ;QACjB,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;IAC3C,CAAC;IAED,WAAW,CAAE,MAAc;QACzB,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAM,CAAA;IAC3C,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,SAAS,EAAK,CAAA;AAC3B,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { Storage } from './types.ts';
2
+ interface FileStorageConfig {
3
+ basePath: string;
4
+ }
5
+ /**
6
+ * File-based storage implementation
7
+ * Uses the filesystem for persistence with atomic writes
8
+ */
9
+ export declare class FileStorage implements Storage {
10
+ #private;
11
+ constructor(config: FileStorageConfig);
12
+ connect(): Promise<void>;
13
+ disconnect(): Promise<void>;
14
+ enqueue(id: string, message: Buffer, timestamp: number): Promise<string | null>;
15
+ dequeue(workerId: string, timeout: number): Promise<Buffer | null>;
16
+ requeue(id: string, message: Buffer, workerId: string): Promise<void>;
17
+ ack(id: string, message: Buffer, workerId: string): Promise<void>;
18
+ getJobState(id: string): Promise<string | null>;
19
+ setJobState(id: string, state: string): Promise<void>;
20
+ deleteJob(id: string): Promise<boolean>;
21
+ getJobStates(ids: string[]): Promise<Map<string, string | null>>;
22
+ setResult(id: string, result: Buffer, ttlMs: number): Promise<void>;
23
+ getResult(id: string): Promise<Buffer | null>;
24
+ setError(id: string, error: Buffer, ttlMs: number): Promise<void>;
25
+ getError(id: string): Promise<Buffer | null>;
26
+ registerWorker(workerId: string, ttlMs: number): Promise<void>;
27
+ refreshWorker(workerId: string, ttlMs: number): Promise<void>;
28
+ unregisterWorker(workerId: string): Promise<void>;
29
+ getWorkers(): Promise<string[]>;
30
+ getProcessingJobs(workerId: string): Promise<Buffer[]>;
31
+ subscribeToJob(id: string, handler: (status: 'completed' | 'failed' | 'failing') => void): Promise<() => Promise<void>>;
32
+ notifyJobComplete(id: string, status: 'completed' | 'failed' | 'failing'): Promise<void>;
33
+ subscribeToEvents(handler: (id: string, event: string) => void): Promise<() => Promise<void>>;
34
+ publishEvent(id: string, event: string): Promise<void>;
35
+ completeJob(id: string, message: Buffer, workerId: string, result: Buffer, resultTtlMs: number): Promise<void>;
36
+ failJob(id: string, message: Buffer, workerId: string, error: Buffer, errorTtlMs: number): Promise<void>;
37
+ retryJob(id: string, message: Buffer, workerId: string, attempts: number): Promise<void>;
38
+ /**
39
+ * Clear all data (useful for testing)
40
+ */
41
+ clear(): Promise<void>;
42
+ }
43
+ export {};
44
+ //# sourceMappingURL=file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/storage/file.ts"],"names":[],"mappings":"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"}