@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.
- package/README.md +511 -0
- package/dist/consumer.d.ts +43 -0
- package/dist/consumer.d.ts.map +1 -0
- package/dist/consumer.js +214 -0
- package/dist/consumer.js.map +1 -0
- package/dist/errors.d.ts +60 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +141 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/producer.d.ts +39 -0
- package/dist/producer.d.ts.map +1 -0
- package/dist/producer.js +163 -0
- package/dist/producer.js.map +1 -0
- package/dist/queue.d.ts +42 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +153 -0
- package/dist/queue.js.map +1 -0
- package/dist/reaper.d.ts +52 -0
- package/dist/reaper.d.ts.map +1 -0
- package/dist/reaper.js +376 -0
- package/dist/reaper.js.map +1 -0
- package/dist/serde/index.d.ts +19 -0
- package/dist/serde/index.d.ts.map +1 -0
- package/dist/serde/index.js +18 -0
- package/dist/serde/index.js.map +1 -0
- package/dist/storage/file.d.ts +44 -0
- package/dist/storage/file.d.ts.map +1 -0
- package/dist/storage/file.js +601 -0
- package/dist/storage/file.js.map +1 -0
- package/dist/storage/memory.d.ts +39 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +292 -0
- package/dist/storage/memory.js.map +1 -0
- package/dist/storage/redis.d.ts +47 -0
- package/dist/storage/redis.d.ts.map +1 -0
- package/dist/storage/redis.js +317 -0
- package/dist/storage/redis.js.map +1 -0
- package/dist/storage/types.d.ts +179 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +2 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/types.d.ts +126 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/id.d.ts +10 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +18 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/state.d.ts +13 -0
- package/dist/utils/state.d.ts.map +1 -0
- package/dist/utils/state.js +22 -0
- package/dist/utils/state.js.map +1 -0
- package/package.json +45 -9
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { EventEmitter } from 'node:events';
|
|
5
|
+
import { Redis } from 'iovalkey';
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
/**
|
|
8
|
+
* Redis/Valkey storage implementation
|
|
9
|
+
*/
|
|
10
|
+
export class RedisStorage {
|
|
11
|
+
#url;
|
|
12
|
+
#keyPrefix;
|
|
13
|
+
#client = null;
|
|
14
|
+
#blockingClient = null; // Single blocking client for BLMOVE
|
|
15
|
+
#subscriber = null;
|
|
16
|
+
#scriptSHAs = null;
|
|
17
|
+
#eventEmitter = new EventEmitter({ captureRejections: true });
|
|
18
|
+
#notifyEmitter = new EventEmitter({ captureRejections: true });
|
|
19
|
+
#eventSubscription = false;
|
|
20
|
+
constructor(config = {}) {
|
|
21
|
+
this.#url = config.url ?? process.env.REDIS_URL ?? 'redis://localhost:6379';
|
|
22
|
+
this.#keyPrefix = config.keyPrefix ?? 'jq:';
|
|
23
|
+
// Disable max listeners warning for high-throughput scenarios
|
|
24
|
+
this.#eventEmitter.setMaxListeners(0);
|
|
25
|
+
this.#notifyEmitter.setMaxListeners(0);
|
|
26
|
+
}
|
|
27
|
+
// Key helpers
|
|
28
|
+
#key(name) {
|
|
29
|
+
return `${this.#keyPrefix}${name}`;
|
|
30
|
+
}
|
|
31
|
+
#jobsKey() {
|
|
32
|
+
return this.#key('jobs');
|
|
33
|
+
}
|
|
34
|
+
#queueKey() {
|
|
35
|
+
return this.#key('queue');
|
|
36
|
+
}
|
|
37
|
+
#processingKey(workerId) {
|
|
38
|
+
return this.#key(`processing:${workerId}`);
|
|
39
|
+
}
|
|
40
|
+
#resultsKey() {
|
|
41
|
+
return this.#key('results');
|
|
42
|
+
}
|
|
43
|
+
#errorsKey() {
|
|
44
|
+
return this.#key('errors');
|
|
45
|
+
}
|
|
46
|
+
#workersKey() {
|
|
47
|
+
return this.#key('workers');
|
|
48
|
+
}
|
|
49
|
+
#reaperLockKey() {
|
|
50
|
+
return this.#key('reaper:lock');
|
|
51
|
+
}
|
|
52
|
+
async connect() {
|
|
53
|
+
if (this.#client)
|
|
54
|
+
return;
|
|
55
|
+
this.#client = new Redis(this.#url);
|
|
56
|
+
this.#subscriber = new Redis(this.#url);
|
|
57
|
+
this.#blockingClient = new Redis(this.#url);
|
|
58
|
+
// Load Lua scripts
|
|
59
|
+
await this.#loadScripts();
|
|
60
|
+
// Set up pub/sub message handler
|
|
61
|
+
this.#subscriber.on('message', (channel, message) => {
|
|
62
|
+
this.#handlePubSubMessage(channel, message);
|
|
63
|
+
});
|
|
64
|
+
this.#subscriber.on('pmessage', (_pattern, channel, message) => {
|
|
65
|
+
this.#handlePubSubMessage(channel, message);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
async disconnect() {
|
|
69
|
+
if (this.#subscriber) {
|
|
70
|
+
this.#subscriber.disconnect();
|
|
71
|
+
this.#subscriber = null;
|
|
72
|
+
}
|
|
73
|
+
if (this.#blockingClient) {
|
|
74
|
+
this.#blockingClient.disconnect();
|
|
75
|
+
this.#blockingClient = null;
|
|
76
|
+
}
|
|
77
|
+
if (this.#client) {
|
|
78
|
+
this.#client.disconnect();
|
|
79
|
+
this.#client = null;
|
|
80
|
+
}
|
|
81
|
+
this.#eventEmitter.removeAllListeners();
|
|
82
|
+
this.#notifyEmitter.removeAllListeners();
|
|
83
|
+
this.#eventSubscription = false;
|
|
84
|
+
}
|
|
85
|
+
async #loadScripts() {
|
|
86
|
+
const scriptsDir = join(__dirname, '..', '..', 'redis-scripts');
|
|
87
|
+
const enqueueScript = readFileSync(join(scriptsDir, 'enqueue.lua'), 'utf8');
|
|
88
|
+
const completeScript = readFileSync(join(scriptsDir, 'complete.lua'), 'utf8');
|
|
89
|
+
const failScript = readFileSync(join(scriptsDir, 'fail.lua'), 'utf8');
|
|
90
|
+
const retryScript = readFileSync(join(scriptsDir, 'retry.lua'), 'utf8');
|
|
91
|
+
const cancelScript = readFileSync(join(scriptsDir, 'cancel.lua'), 'utf8');
|
|
92
|
+
const renewLeaderLockScript = readFileSync(join(scriptsDir, 'renew-leader-lock.lua'), 'utf8');
|
|
93
|
+
const releaseLeaderLockScript = readFileSync(join(scriptsDir, 'release-leader-lock.lua'), 'utf8');
|
|
94
|
+
const [enqueue, complete, fail, retry, cancel, renewLeaderLock, releaseLeaderLock] = await Promise.all([
|
|
95
|
+
this.#client.script('LOAD', enqueueScript),
|
|
96
|
+
this.#client.script('LOAD', completeScript),
|
|
97
|
+
this.#client.script('LOAD', failScript),
|
|
98
|
+
this.#client.script('LOAD', retryScript),
|
|
99
|
+
this.#client.script('LOAD', cancelScript),
|
|
100
|
+
this.#client.script('LOAD', renewLeaderLockScript),
|
|
101
|
+
this.#client.script('LOAD', releaseLeaderLockScript)
|
|
102
|
+
]);
|
|
103
|
+
this.#scriptSHAs = { enqueue, complete, fail, retry, cancel, renewLeaderLock, releaseLeaderLock };
|
|
104
|
+
}
|
|
105
|
+
#notifyChannelPrefix() {
|
|
106
|
+
return `${this.#keyPrefix}notify:`;
|
|
107
|
+
}
|
|
108
|
+
#eventsChannel() {
|
|
109
|
+
return `${this.#keyPrefix}events`;
|
|
110
|
+
}
|
|
111
|
+
#handlePubSubMessage(channel, message) {
|
|
112
|
+
const notifyPrefix = this.#notifyChannelPrefix();
|
|
113
|
+
const eventsChannel = this.#eventsChannel();
|
|
114
|
+
// Job notification (prefix:notify:jobId)
|
|
115
|
+
if (channel.startsWith(notifyPrefix)) {
|
|
116
|
+
const jobId = channel.substring(notifyPrefix.length);
|
|
117
|
+
this.#notifyEmitter.emit(`notify:${jobId}`, message);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
// Job events (prefix:events)
|
|
121
|
+
if (channel === eventsChannel) {
|
|
122
|
+
const [id, event] = message.split(':');
|
|
123
|
+
this.#eventEmitter.emit('event', id, event);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async enqueue(id, message, timestamp) {
|
|
127
|
+
const state = `queued:${timestamp}`;
|
|
128
|
+
const result = await this.#client.evalsha(this.#scriptSHAs.enqueue, 2, this.#jobsKey(), this.#queueKey(), id, message, state);
|
|
129
|
+
// If this is a new job (not duplicate), publish the queued event
|
|
130
|
+
if (result === null) {
|
|
131
|
+
await this.publishEvent(id, 'queued');
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
async dequeue(workerId, timeout) {
|
|
136
|
+
// BLMOVE: blocking move from queue to processing queue
|
|
137
|
+
// A single blocking client can handle multiple concurrent BLMOVE calls -
|
|
138
|
+
// iovalkey multiplexes them and Redis queues them internally.
|
|
139
|
+
const result = await this.#blockingClient.blmove(this.#queueKey(), this.#processingKey(workerId), 'LEFT', 'RIGHT', timeout);
|
|
140
|
+
return result ? Buffer.from(result) : null;
|
|
141
|
+
}
|
|
142
|
+
async requeue(id, message, workerId) {
|
|
143
|
+
// Remove from processing queue and add to front of main queue
|
|
144
|
+
await this.#client.lrem(this.#processingKey(workerId), 1, message);
|
|
145
|
+
await this.#client.lpush(this.#queueKey(), message);
|
|
146
|
+
}
|
|
147
|
+
async ack(id, message, workerId) {
|
|
148
|
+
await this.#client.lrem(this.#processingKey(workerId), 1, message);
|
|
149
|
+
}
|
|
150
|
+
async getJobState(id) {
|
|
151
|
+
const state = await this.#client.hget(this.#jobsKey(), id);
|
|
152
|
+
return state;
|
|
153
|
+
}
|
|
154
|
+
async setJobState(id, state) {
|
|
155
|
+
await this.#client.hset(this.#jobsKey(), id, state);
|
|
156
|
+
}
|
|
157
|
+
async deleteJob(id) {
|
|
158
|
+
const result = await this.#client.evalsha(this.#scriptSHAs.cancel, 1, this.#jobsKey(), id);
|
|
159
|
+
return result === 1;
|
|
160
|
+
}
|
|
161
|
+
async getJobStates(ids) {
|
|
162
|
+
if (ids.length === 0) {
|
|
163
|
+
return new Map();
|
|
164
|
+
}
|
|
165
|
+
const states = await this.#client.hmget(this.#jobsKey(), ...ids);
|
|
166
|
+
const result = new Map();
|
|
167
|
+
for (let i = 0; i < ids.length; i++) {
|
|
168
|
+
result.set(ids[i], states[i]);
|
|
169
|
+
}
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
async setResult(id, result, ttlMs) {
|
|
173
|
+
await this.#client.hset(this.#resultsKey(), id, result);
|
|
174
|
+
// Note: HEXPIRE is not widely supported, so we set TTL on the whole hash
|
|
175
|
+
// For production, consider using separate keys per result
|
|
176
|
+
}
|
|
177
|
+
async getResult(id) {
|
|
178
|
+
const result = await this.#client.hgetBuffer(this.#resultsKey(), id);
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
async setError(id, error, ttlMs) {
|
|
182
|
+
await this.#client.hset(this.#errorsKey(), id, error);
|
|
183
|
+
}
|
|
184
|
+
async getError(id) {
|
|
185
|
+
const result = await this.#client.hgetBuffer(this.#errorsKey(), id);
|
|
186
|
+
return result;
|
|
187
|
+
}
|
|
188
|
+
async registerWorker(workerId, ttlMs) {
|
|
189
|
+
await this.#client.hset(this.#workersKey(), workerId, Date.now().toString());
|
|
190
|
+
// Set expiry on the worker entry
|
|
191
|
+
await this.#client.pexpire(this.#workersKey(), ttlMs);
|
|
192
|
+
}
|
|
193
|
+
async refreshWorker(workerId, ttlMs) {
|
|
194
|
+
await this.registerWorker(workerId, ttlMs);
|
|
195
|
+
}
|
|
196
|
+
async unregisterWorker(workerId) {
|
|
197
|
+
if (!this.#client)
|
|
198
|
+
return;
|
|
199
|
+
await this.#client.hdel(this.#workersKey(), workerId);
|
|
200
|
+
// Also clear the processing queue
|
|
201
|
+
await this.#client.del(this.#processingKey(workerId));
|
|
202
|
+
}
|
|
203
|
+
async getWorkers() {
|
|
204
|
+
const workers = await this.#client.hkeys(this.#workersKey());
|
|
205
|
+
return workers;
|
|
206
|
+
}
|
|
207
|
+
async getProcessingJobs(workerId) {
|
|
208
|
+
const jobs = await this.#client.lrangeBuffer(this.#processingKey(workerId), 0, -1);
|
|
209
|
+
return jobs;
|
|
210
|
+
}
|
|
211
|
+
async subscribeToJob(id, handler) {
|
|
212
|
+
const eventName = `notify:${id}`;
|
|
213
|
+
this.#notifyEmitter.on(eventName, handler);
|
|
214
|
+
// Subscribe to the job notification channel
|
|
215
|
+
const channel = `${this.#notifyChannelPrefix()}${id}`;
|
|
216
|
+
await this.#subscriber.subscribe(channel);
|
|
217
|
+
return async () => {
|
|
218
|
+
this.#notifyEmitter.off(eventName, handler);
|
|
219
|
+
await this.#subscriber.unsubscribe(channel);
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
async notifyJobComplete(id, status) {
|
|
223
|
+
const channel = `${this.#notifyChannelPrefix()}${id}`;
|
|
224
|
+
await this.#client.publish(channel, status);
|
|
225
|
+
}
|
|
226
|
+
async subscribeToEvents(handler) {
|
|
227
|
+
this.#eventEmitter.on('event', handler);
|
|
228
|
+
if (!this.#eventSubscription) {
|
|
229
|
+
await this.#subscriber.subscribe(this.#eventsChannel());
|
|
230
|
+
this.#eventSubscription = true;
|
|
231
|
+
}
|
|
232
|
+
return async () => {
|
|
233
|
+
this.#eventEmitter.off('event', handler);
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
async publishEvent(id, event) {
|
|
237
|
+
await this.#client.publish(this.#eventsChannel(), `${id}:${event}`);
|
|
238
|
+
}
|
|
239
|
+
async completeJob(id, message, workerId, result, resultTtlMs) {
|
|
240
|
+
const timestamp = Date.now();
|
|
241
|
+
const state = `completed:${timestamp}`;
|
|
242
|
+
await this.#client.evalsha(this.#scriptSHAs.complete, 3, this.#jobsKey(), this.#resultsKey(), this.#processingKey(workerId), id, message, state, result, resultTtlMs.toString());
|
|
243
|
+
// Notify subscribers and publish event
|
|
244
|
+
await this.notifyJobComplete(id, 'completed');
|
|
245
|
+
await this.publishEvent(id, 'completed');
|
|
246
|
+
}
|
|
247
|
+
async failJob(id, message, workerId, error, errorTtlMs) {
|
|
248
|
+
const timestamp = Date.now();
|
|
249
|
+
const state = `failed:${timestamp}`;
|
|
250
|
+
await this.#client.evalsha(this.#scriptSHAs.fail, 3, this.#jobsKey(), this.#errorsKey(), this.#processingKey(workerId), id, message, state, error, errorTtlMs.toString());
|
|
251
|
+
// Notify subscribers and publish event
|
|
252
|
+
await this.notifyJobComplete(id, 'failed');
|
|
253
|
+
await this.publishEvent(id, 'failed');
|
|
254
|
+
}
|
|
255
|
+
async retryJob(id, message, workerId, attempts) {
|
|
256
|
+
const timestamp = Date.now();
|
|
257
|
+
const state = `failing:${timestamp}:${attempts}`;
|
|
258
|
+
// Get the old message from processing queue to remove it
|
|
259
|
+
const processingJobs = await this.getProcessingJobs(workerId);
|
|
260
|
+
let oldMessage = null;
|
|
261
|
+
// Find the message with matching job id
|
|
262
|
+
for (const job of processingJobs) {
|
|
263
|
+
try {
|
|
264
|
+
const parsed = JSON.parse(job.toString());
|
|
265
|
+
if (parsed.id === id) {
|
|
266
|
+
oldMessage = job;
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
// Ignore parse errors
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (oldMessage) {
|
|
275
|
+
await this.#client.evalsha(this.#scriptSHAs.retry, 3, this.#jobsKey(), this.#queueKey(), this.#processingKey(workerId), id, message, oldMessage, state);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
// Fallback: just set state and push new message
|
|
279
|
+
await this.setJobState(id, state);
|
|
280
|
+
await this.#client.lpush(this.#queueKey(), message);
|
|
281
|
+
await this.notifyJobComplete(id, 'failing');
|
|
282
|
+
await this.publishEvent(id, 'failing');
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Clear all data (useful for testing)
|
|
287
|
+
*/
|
|
288
|
+
async clear() {
|
|
289
|
+
// If not connected, nothing to clear
|
|
290
|
+
if (!this.#client) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
const keys = await this.#client.keys(`${this.#keyPrefix}*`);
|
|
294
|
+
if (keys.length > 0) {
|
|
295
|
+
await this.#client.del(...keys);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
299
|
+
// LEADER ELECTION
|
|
300
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
301
|
+
async acquireLeaderLock(lockKey, ownerId, ttlMs) {
|
|
302
|
+
// SET NX PX: Set only if Not eXists, with PX milliseconds expiry
|
|
303
|
+
const result = await this.#client.set(this.#key(lockKey), ownerId, 'PX', ttlMs, 'NX');
|
|
304
|
+
return result === 'OK';
|
|
305
|
+
}
|
|
306
|
+
async renewLeaderLock(lockKey, ownerId, ttlMs) {
|
|
307
|
+
const result = await this.#client.evalsha(this.#scriptSHAs.renewLeaderLock, 1, this.#key(lockKey), ownerId, ttlMs.toString());
|
|
308
|
+
return result === 1;
|
|
309
|
+
}
|
|
310
|
+
async releaseLeaderLock(lockKey, ownerId) {
|
|
311
|
+
if (!this.#client)
|
|
312
|
+
return false;
|
|
313
|
+
const result = await this.#client.evalsha(this.#scriptSHAs.releaseLeaderLock, 1, this.#key(lockKey), ownerId);
|
|
314
|
+
return result === 1;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=redis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../src/storage/redis.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage interface for pluggable backends
|
|
3
|
+
*/
|
|
4
|
+
export interface Storage {
|
|
5
|
+
/**
|
|
6
|
+
* Initialize the storage connection.
|
|
7
|
+
* Called once when Queue.start() is invoked.
|
|
8
|
+
*/
|
|
9
|
+
connect(): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Close the storage connection gracefully.
|
|
12
|
+
* Called when Queue.stop() is invoked.
|
|
13
|
+
*/
|
|
14
|
+
disconnect(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Atomically enqueue a job if not already present.
|
|
17
|
+
* Must check for duplicates and set initial state in one atomic operation.
|
|
18
|
+
*
|
|
19
|
+
* @returns null if job was enqueued, existing state string if duplicate
|
|
20
|
+
*/
|
|
21
|
+
enqueue(id: string, message: Buffer, timestamp: number): Promise<string | null>;
|
|
22
|
+
/**
|
|
23
|
+
* Blocking dequeue: move a job from main queue to worker's processing queue.
|
|
24
|
+
* Should block up to `timeout` seconds if queue is empty.
|
|
25
|
+
*
|
|
26
|
+
* @returns The job message, or null if timeout
|
|
27
|
+
*/
|
|
28
|
+
dequeue(workerId: string, timeout: number): Promise<Buffer | null>;
|
|
29
|
+
/**
|
|
30
|
+
* Move a job from worker's processing queue back to main queue.
|
|
31
|
+
* Used for retries and stall recovery.
|
|
32
|
+
*/
|
|
33
|
+
requeue(id: string, message: Buffer, workerId: string): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Remove a job from worker's processing queue (after completion or failure).
|
|
36
|
+
*/
|
|
37
|
+
ack(id: string, message: Buffer, workerId: string): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Get the current state of a job.
|
|
40
|
+
* State format: "status:timestamp[:workerId]"
|
|
41
|
+
*
|
|
42
|
+
* @returns State string, or null if job doesn't exist
|
|
43
|
+
*/
|
|
44
|
+
getJobState(id: string): Promise<string | null>;
|
|
45
|
+
/**
|
|
46
|
+
* Set the state of a job.
|
|
47
|
+
* Should also publish a notification for state changes.
|
|
48
|
+
*/
|
|
49
|
+
setJobState(id: string, state: string): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Delete a job from the jobs registry.
|
|
52
|
+
* Used for cancellation.
|
|
53
|
+
*
|
|
54
|
+
* @returns true if job existed and was deleted
|
|
55
|
+
*/
|
|
56
|
+
deleteJob(id: string): Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Get multiple job states in one call (batch operation).
|
|
59
|
+
*/
|
|
60
|
+
getJobStates(ids: string[]): Promise<Map<string, string | null>>;
|
|
61
|
+
/**
|
|
62
|
+
* Store a job result with TTL.
|
|
63
|
+
*/
|
|
64
|
+
setResult(id: string, result: Buffer, ttlMs: number): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Retrieve a stored job result.
|
|
67
|
+
*
|
|
68
|
+
* @returns Result buffer, or null if not found/expired
|
|
69
|
+
*/
|
|
70
|
+
getResult(id: string): Promise<Buffer | null>;
|
|
71
|
+
/**
|
|
72
|
+
* Store a job error with TTL.
|
|
73
|
+
*/
|
|
74
|
+
setError(id: string, error: Buffer, ttlMs: number): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Retrieve a stored job error.
|
|
77
|
+
*/
|
|
78
|
+
getError(id: string): Promise<Buffer | null>;
|
|
79
|
+
/**
|
|
80
|
+
* Register a worker as active.
|
|
81
|
+
* Should set a TTL so crashed workers are automatically removed.
|
|
82
|
+
*/
|
|
83
|
+
registerWorker(workerId: string, ttlMs: number): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Refresh worker registration (heartbeat).
|
|
86
|
+
*/
|
|
87
|
+
refreshWorker(workerId: string, ttlMs: number): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Unregister a worker (graceful shutdown).
|
|
90
|
+
*/
|
|
91
|
+
unregisterWorker(workerId: string): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Get list of all registered workers.
|
|
94
|
+
*/
|
|
95
|
+
getWorkers(): Promise<string[]>;
|
|
96
|
+
/**
|
|
97
|
+
* Get all jobs in a worker's processing queue.
|
|
98
|
+
* Used by reaper to find stalled jobs.
|
|
99
|
+
*/
|
|
100
|
+
getProcessingJobs(workerId: string): Promise<Buffer[]>;
|
|
101
|
+
/**
|
|
102
|
+
* Subscribe to notifications for a specific job.
|
|
103
|
+
* Used by enqueueAndWait to receive completion notification.
|
|
104
|
+
*
|
|
105
|
+
* @param id - Job ID to subscribe to
|
|
106
|
+
* @param handler - Called when notification received
|
|
107
|
+
* @returns Unsubscribe function
|
|
108
|
+
*/
|
|
109
|
+
subscribeToJob(id: string, handler: (status: 'completed' | 'failed' | 'failing') => void): Promise<() => Promise<void>>;
|
|
110
|
+
/**
|
|
111
|
+
* Publish a job completion/failure notification.
|
|
112
|
+
* Called by worker after job finishes or is retried.
|
|
113
|
+
*/
|
|
114
|
+
notifyJobComplete(id: string, status: 'completed' | 'failed' | 'failing'): Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* Subscribe to all job state change events.
|
|
117
|
+
* Used by reaper and monitoring.
|
|
118
|
+
*
|
|
119
|
+
* @returns Unsubscribe function
|
|
120
|
+
*/
|
|
121
|
+
subscribeToEvents(handler: (id: string, event: string) => void): Promise<() => Promise<void>>;
|
|
122
|
+
/**
|
|
123
|
+
* Publish a job state change event.
|
|
124
|
+
*/
|
|
125
|
+
publishEvent(id: string, event: string): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Try to acquire the reaper leader lock.
|
|
128
|
+
* Uses SET NX PX pattern for atomic acquisition.
|
|
129
|
+
*
|
|
130
|
+
* @param lockKey - The lock key name
|
|
131
|
+
* @param ownerId - Unique identifier for this reaper instance
|
|
132
|
+
* @param ttlMs - Lock TTL in milliseconds
|
|
133
|
+
* @returns true if lock was acquired, false if already held by another
|
|
134
|
+
*/
|
|
135
|
+
acquireLeaderLock?(lockKey: string, ownerId: string, ttlMs: number): Promise<boolean>;
|
|
136
|
+
/**
|
|
137
|
+
* Renew the leader lock if still owned by this reaper.
|
|
138
|
+
* Extends the TTL atomically only if the current owner matches.
|
|
139
|
+
*
|
|
140
|
+
* @param lockKey - The lock key name
|
|
141
|
+
* @param ownerId - Unique identifier for this reaper instance
|
|
142
|
+
* @param ttlMs - New TTL in milliseconds
|
|
143
|
+
* @returns true if lock was renewed, false if not owned
|
|
144
|
+
*/
|
|
145
|
+
renewLeaderLock?(lockKey: string, ownerId: string, ttlMs: number): Promise<boolean>;
|
|
146
|
+
/**
|
|
147
|
+
* Release the leader lock if owned by this reaper.
|
|
148
|
+
* Deletes the lock atomically only if the current owner matches.
|
|
149
|
+
*
|
|
150
|
+
* @param lockKey - The lock key name
|
|
151
|
+
* @param ownerId - Unique identifier for this reaper instance
|
|
152
|
+
* @returns true if lock was released, false if not owned
|
|
153
|
+
*/
|
|
154
|
+
releaseLeaderLock?(lockKey: string, ownerId: string): Promise<boolean>;
|
|
155
|
+
/**
|
|
156
|
+
* Atomically complete a job:
|
|
157
|
+
* - Set state to completed
|
|
158
|
+
* - Store result
|
|
159
|
+
* - Remove from processing queue
|
|
160
|
+
* - Publish notification
|
|
161
|
+
*/
|
|
162
|
+
completeJob(id: string, message: Buffer, workerId: string, result: Buffer, resultTtlMs: number): Promise<void>;
|
|
163
|
+
/**
|
|
164
|
+
* Atomically fail a job:
|
|
165
|
+
* - Set state to failed
|
|
166
|
+
* - Store error
|
|
167
|
+
* - Remove from processing queue
|
|
168
|
+
* - Publish notification
|
|
169
|
+
*/
|
|
170
|
+
failJob(id: string, message: Buffer, workerId: string, error: Buffer, errorTtlMs: number): Promise<void>;
|
|
171
|
+
/**
|
|
172
|
+
* Atomically retry a job:
|
|
173
|
+
* - Set state to failing
|
|
174
|
+
* - Move from processing queue to main queue
|
|
175
|
+
* - Publish event
|
|
176
|
+
*/
|
|
177
|
+
retryJob(id: string, message: Buffer, workerId: string, attempts: number): Promise<void>;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/storage/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/storage/types.ts"],"names":[],"mappings":""}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { Storage } from './storage/types.ts';
|
|
2
|
+
import type { Serde } from './serde/index.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Message stored in the queue
|
|
5
|
+
*/
|
|
6
|
+
export interface QueueMessage<TPayload> {
|
|
7
|
+
id: string;
|
|
8
|
+
payload: TPayload;
|
|
9
|
+
createdAt: number;
|
|
10
|
+
attempts: number;
|
|
11
|
+
maxAttempts: number;
|
|
12
|
+
correlationId?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Job state in the jobs registry
|
|
16
|
+
*/
|
|
17
|
+
export type MessageState = 'queued' | 'processing' | 'failing' | 'completed' | 'failed';
|
|
18
|
+
/**
|
|
19
|
+
* Serialized error information
|
|
20
|
+
*/
|
|
21
|
+
export interface SerializedError {
|
|
22
|
+
message: string;
|
|
23
|
+
code?: string;
|
|
24
|
+
stack?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Job status with metadata
|
|
28
|
+
*/
|
|
29
|
+
export interface MessageStatus<TResult = unknown> {
|
|
30
|
+
id: string;
|
|
31
|
+
state: MessageState;
|
|
32
|
+
createdAt: number;
|
|
33
|
+
attempts: number;
|
|
34
|
+
result?: TResult;
|
|
35
|
+
error?: SerializedError;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Options for enqueue operation
|
|
39
|
+
*/
|
|
40
|
+
export interface EnqueueOptions {
|
|
41
|
+
maxAttempts?: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Options for enqueueAndWait operation
|
|
45
|
+
*/
|
|
46
|
+
export interface EnqueueAndWaitOptions extends EnqueueOptions {
|
|
47
|
+
timeout?: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Result of enqueue operation
|
|
51
|
+
*/
|
|
52
|
+
export type EnqueueResult<TResult = unknown> = {
|
|
53
|
+
status: 'queued';
|
|
54
|
+
} | {
|
|
55
|
+
status: 'duplicate';
|
|
56
|
+
existingState: MessageState;
|
|
57
|
+
} | {
|
|
58
|
+
status: 'completed';
|
|
59
|
+
result: TResult;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Result of cancel operation
|
|
63
|
+
*/
|
|
64
|
+
export type CancelResult = {
|
|
65
|
+
status: 'cancelled';
|
|
66
|
+
} | {
|
|
67
|
+
status: 'not_found';
|
|
68
|
+
} | {
|
|
69
|
+
status: 'processing';
|
|
70
|
+
} | {
|
|
71
|
+
status: 'completed';
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Job passed to the handler
|
|
75
|
+
*/
|
|
76
|
+
export interface Job<TPayload> {
|
|
77
|
+
id: string;
|
|
78
|
+
payload: TPayload;
|
|
79
|
+
attempts: number;
|
|
80
|
+
signal: AbortSignal;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Job handler function
|
|
84
|
+
*/
|
|
85
|
+
export type JobHandler<TPayload, TResult> = ((job: Job<TPayload>) => Promise<TResult>) | ((job: Job<TPayload>, callback: (err: Error | null, result?: TResult) => void) => void);
|
|
86
|
+
/**
|
|
87
|
+
* Queue configuration
|
|
88
|
+
*/
|
|
89
|
+
export interface QueueConfig<TPayload, TResult> {
|
|
90
|
+
/** Storage backend (required) */
|
|
91
|
+
storage: Storage;
|
|
92
|
+
/** Payload serializer (default: JSON) */
|
|
93
|
+
payloadSerde?: Serde<TPayload>;
|
|
94
|
+
/** Result serializer (default: JSON) */
|
|
95
|
+
resultSerde?: Serde<TResult>;
|
|
96
|
+
/** Unique worker ID (default: random UUID) */
|
|
97
|
+
workerId?: string;
|
|
98
|
+
/** Parallel job processing (default: 1) */
|
|
99
|
+
concurrency?: number;
|
|
100
|
+
/** Blocking dequeue timeout in seconds (default: 5) */
|
|
101
|
+
blockTimeout?: number;
|
|
102
|
+
/** Default max retry attempts (default: 3) */
|
|
103
|
+
maxRetries?: number;
|
|
104
|
+
/** Max processing time before job is considered stalled in ms (default: 30000) */
|
|
105
|
+
visibilityTimeout?: number;
|
|
106
|
+
/** TTL for processing queue keys in ms (default: 604800000 = 7 days) */
|
|
107
|
+
processingQueueTTL?: number;
|
|
108
|
+
/** TTL for stored results and errors in ms (default: 3600000 = 1 hour) */
|
|
109
|
+
resultTTL?: number;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Queue events (tuple format for EventEmitter)
|
|
113
|
+
*/
|
|
114
|
+
export interface QueueEvents<TResult> {
|
|
115
|
+
started: [];
|
|
116
|
+
stopped: [];
|
|
117
|
+
error: [error: Error];
|
|
118
|
+
enqueued: [id: string];
|
|
119
|
+
completed: [id: string, result: TResult];
|
|
120
|
+
failed: [id: string, error: Error];
|
|
121
|
+
failing: [id: string, error: Error, attempt: number];
|
|
122
|
+
requeued: [id: string];
|
|
123
|
+
cancelled: [id: string];
|
|
124
|
+
stalled: [id: string];
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED