@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,601 @@
|
|
|
1
|
+
import fastWriteAtomic from 'fast-write-atomic';
|
|
2
|
+
import { EventEmitter } from 'node:events';
|
|
3
|
+
import { mkdir, readdir, readFile, rename, rm, unlink, watch, } from 'node:fs/promises';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
const writeFileAtomic = fastWriteAtomic.promise;
|
|
6
|
+
/**
|
|
7
|
+
* File-based storage implementation
|
|
8
|
+
* Uses the filesystem for persistence with atomic writes
|
|
9
|
+
*/
|
|
10
|
+
export class FileStorage {
|
|
11
|
+
#basePath;
|
|
12
|
+
#queuePath;
|
|
13
|
+
#processingPath;
|
|
14
|
+
#jobsPath;
|
|
15
|
+
#resultsPath;
|
|
16
|
+
#errorsPath;
|
|
17
|
+
#workersPath;
|
|
18
|
+
#notifyPath;
|
|
19
|
+
#sequence = 0;
|
|
20
|
+
#eventEmitter = new EventEmitter({ captureRejections: true });
|
|
21
|
+
#notifyEmitter = new EventEmitter({ captureRejections: true });
|
|
22
|
+
#dequeueWaiters = [];
|
|
23
|
+
#drainingDequeueWaiters = false;
|
|
24
|
+
#dequeueDrainRequested = false;
|
|
25
|
+
#queueWatcher = null;
|
|
26
|
+
#notifyWatcher = null;
|
|
27
|
+
#watchAbortController = null;
|
|
28
|
+
#cleanupInterval = null;
|
|
29
|
+
#connected = false;
|
|
30
|
+
constructor(config) {
|
|
31
|
+
this.#basePath = config.basePath;
|
|
32
|
+
this.#queuePath = join(this.#basePath, 'queue');
|
|
33
|
+
this.#processingPath = join(this.#basePath, 'processing');
|
|
34
|
+
this.#jobsPath = join(this.#basePath, 'jobs');
|
|
35
|
+
this.#resultsPath = join(this.#basePath, 'results');
|
|
36
|
+
this.#errorsPath = join(this.#basePath, 'errors');
|
|
37
|
+
this.#workersPath = join(this.#basePath, 'workers');
|
|
38
|
+
this.#notifyPath = join(this.#basePath, 'notify');
|
|
39
|
+
this.#eventEmitter.setMaxListeners(0);
|
|
40
|
+
this.#notifyEmitter.setMaxListeners(0);
|
|
41
|
+
}
|
|
42
|
+
async connect() {
|
|
43
|
+
if (this.#connected)
|
|
44
|
+
return;
|
|
45
|
+
// Create directory structure
|
|
46
|
+
await Promise.all([
|
|
47
|
+
mkdir(this.#queuePath, { recursive: true }),
|
|
48
|
+
mkdir(this.#processingPath, { recursive: true }),
|
|
49
|
+
mkdir(this.#jobsPath, { recursive: true }),
|
|
50
|
+
mkdir(this.#resultsPath, { recursive: true }),
|
|
51
|
+
mkdir(this.#errorsPath, { recursive: true }),
|
|
52
|
+
mkdir(this.#workersPath, { recursive: true }),
|
|
53
|
+
mkdir(this.#notifyPath, { recursive: true }),
|
|
54
|
+
]);
|
|
55
|
+
// Initialize sequence number from existing queue files
|
|
56
|
+
await this.#initSequence();
|
|
57
|
+
// Start watching directories
|
|
58
|
+
this.#watchAbortController = new AbortController();
|
|
59
|
+
this.#startQueueWatcher();
|
|
60
|
+
this.#startNotifyWatcher();
|
|
61
|
+
// Start cleanup interval
|
|
62
|
+
this.#cleanupInterval = setInterval(() => {
|
|
63
|
+
this.#cleanupExpired().catch(() => { });
|
|
64
|
+
}, 1000);
|
|
65
|
+
this.#connected = true;
|
|
66
|
+
}
|
|
67
|
+
async disconnect() {
|
|
68
|
+
if (!this.#connected)
|
|
69
|
+
return;
|
|
70
|
+
// Stop watchers
|
|
71
|
+
if (this.#watchAbortController) {
|
|
72
|
+
this.#watchAbortController.abort();
|
|
73
|
+
this.#watchAbortController = null;
|
|
74
|
+
}
|
|
75
|
+
// Stop cleanup
|
|
76
|
+
if (this.#cleanupInterval) {
|
|
77
|
+
clearInterval(this.#cleanupInterval);
|
|
78
|
+
this.#cleanupInterval = null;
|
|
79
|
+
}
|
|
80
|
+
// Clear dequeue waiters
|
|
81
|
+
for (const waiter of this.#dequeueWaiters) {
|
|
82
|
+
clearTimeout(waiter.timeoutId);
|
|
83
|
+
waiter.resolve(null);
|
|
84
|
+
}
|
|
85
|
+
this.#dequeueWaiters = [];
|
|
86
|
+
this.#eventEmitter.removeAllListeners();
|
|
87
|
+
this.#notifyEmitter.removeAllListeners();
|
|
88
|
+
this.#connected = false;
|
|
89
|
+
}
|
|
90
|
+
async #initSequence() {
|
|
91
|
+
try {
|
|
92
|
+
const files = await readdir(this.#queuePath);
|
|
93
|
+
let maxSeq = 0;
|
|
94
|
+
for (const file of files) {
|
|
95
|
+
const seq = parseInt(file.split('-')[0], 10);
|
|
96
|
+
if (!isNaN(seq) && seq > maxSeq) {
|
|
97
|
+
maxSeq = seq;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
this.#sequence = maxSeq;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
this.#sequence = 0;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
#startQueueWatcher() {
|
|
107
|
+
if (!this.#watchAbortController)
|
|
108
|
+
return;
|
|
109
|
+
const runWatcher = async () => {
|
|
110
|
+
try {
|
|
111
|
+
const watcher = watch(this.#queuePath, {
|
|
112
|
+
signal: this.#watchAbortController?.signal,
|
|
113
|
+
});
|
|
114
|
+
for await (const event of watcher) {
|
|
115
|
+
if (event.eventType === 'rename' &&
|
|
116
|
+
event.filename?.endsWith('.msg')) {
|
|
117
|
+
this.#notifyDequeueWaiters();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
if (err instanceof Error && err.name === 'AbortError')
|
|
123
|
+
return;
|
|
124
|
+
// Restart watcher on error
|
|
125
|
+
setTimeout(() => this.#startQueueWatcher(), 100);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
runWatcher();
|
|
129
|
+
}
|
|
130
|
+
#startNotifyWatcher() {
|
|
131
|
+
if (!this.#watchAbortController)
|
|
132
|
+
return;
|
|
133
|
+
const runWatcher = async () => {
|
|
134
|
+
try {
|
|
135
|
+
const watcher = watch(this.#notifyPath, {
|
|
136
|
+
signal: this.#watchAbortController?.signal,
|
|
137
|
+
});
|
|
138
|
+
for await (const event of watcher) {
|
|
139
|
+
if (event.eventType === 'rename' &&
|
|
140
|
+
event.filename?.endsWith('.notify')) {
|
|
141
|
+
// Read and process notification
|
|
142
|
+
const notifyFile = join(this.#notifyPath, event.filename);
|
|
143
|
+
try {
|
|
144
|
+
const content = await readFile(notifyFile, 'utf8');
|
|
145
|
+
const [id, status] = content.split(':');
|
|
146
|
+
this.#notifyEmitter.emit(`notify:${id}`, status);
|
|
147
|
+
// Clean up notification file
|
|
148
|
+
await unlink(notifyFile).catch(() => { });
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// File may have been deleted already
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
if (err instanceof Error && err.name === 'AbortError')
|
|
158
|
+
return;
|
|
159
|
+
setTimeout(() => this.#startNotifyWatcher(), 100);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
runWatcher();
|
|
163
|
+
}
|
|
164
|
+
async #notifyDequeueWaiters() {
|
|
165
|
+
// This method may be triggered by both enqueue() and fs watcher events.
|
|
166
|
+
// Serialize runs to avoid races that can resolve/shift the wrong waiter.
|
|
167
|
+
if (this.#drainingDequeueWaiters) {
|
|
168
|
+
this.#dequeueDrainRequested = true;
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
this.#drainingDequeueWaiters = true;
|
|
172
|
+
try {
|
|
173
|
+
do {
|
|
174
|
+
this.#dequeueDrainRequested = false;
|
|
175
|
+
while (this.#dequeueWaiters.length > 0) {
|
|
176
|
+
const waiter = this.#dequeueWaiters[0];
|
|
177
|
+
const message = await this.#getNextQueueMessage(waiter.workerId);
|
|
178
|
+
if (!message) {
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
this.#dequeueWaiters.shift();
|
|
182
|
+
clearTimeout(waiter.timeoutId);
|
|
183
|
+
waiter.resolve(message);
|
|
184
|
+
}
|
|
185
|
+
} while (this.#dequeueDrainRequested);
|
|
186
|
+
}
|
|
187
|
+
finally {
|
|
188
|
+
this.#drainingDequeueWaiters = false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async #getNextQueueMessage(workerId) {
|
|
192
|
+
const files = await this.#getQueueFiles();
|
|
193
|
+
if (files.length === 0)
|
|
194
|
+
return null;
|
|
195
|
+
// Ensure processing directory exists
|
|
196
|
+
await mkdir(join(this.#processingPath, workerId), { recursive: true });
|
|
197
|
+
// Try to claim files until one succeeds
|
|
198
|
+
for (const file of files) {
|
|
199
|
+
const srcPath = join(this.#queuePath, file);
|
|
200
|
+
const id = this.#extractIdFromFilename(file);
|
|
201
|
+
const dstPath = join(this.#processingPath, workerId, `${id}.msg`);
|
|
202
|
+
try {
|
|
203
|
+
// Atomic rename - only one worker can succeed on same filesystem
|
|
204
|
+
await rename(srcPath, dstPath);
|
|
205
|
+
// Only read after successful claim
|
|
206
|
+
return await readFile(dstPath);
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
// Another worker claimed this file, try the next one
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
async #getQueueFiles() {
|
|
216
|
+
try {
|
|
217
|
+
const files = await readdir(this.#queuePath);
|
|
218
|
+
return files
|
|
219
|
+
.filter((f) => f.endsWith('.msg'))
|
|
220
|
+
.sort((a, b) => {
|
|
221
|
+
const seqA = parseInt(a.split('-')[0], 10);
|
|
222
|
+
const seqB = parseInt(b.split('-')[0], 10);
|
|
223
|
+
return seqA - seqB;
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
#extractIdFromFilename(filename) {
|
|
231
|
+
// Format: sequence-id.msg
|
|
232
|
+
const withoutExt = filename.replace('.msg', '');
|
|
233
|
+
const dashIndex = withoutExt.indexOf('-');
|
|
234
|
+
return dashIndex >= 0 ? withoutExt.substring(dashIndex + 1) : withoutExt;
|
|
235
|
+
}
|
|
236
|
+
async enqueue(id, message, timestamp) {
|
|
237
|
+
const jobFile = join(this.#jobsPath, `${id}.state`);
|
|
238
|
+
// Check if job already exists
|
|
239
|
+
try {
|
|
240
|
+
const existing = await readFile(jobFile, 'utf8');
|
|
241
|
+
return existing;
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
// Job doesn't exist, continue
|
|
245
|
+
}
|
|
246
|
+
// Create job state atomically
|
|
247
|
+
const state = `queued:${timestamp}`;
|
|
248
|
+
try {
|
|
249
|
+
// Try to create job file - if it exists, this will overwrite but we check above
|
|
250
|
+
await writeFileAtomic(jobFile, state, { mode: 0o644 });
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
// Check if another process created it
|
|
254
|
+
try {
|
|
255
|
+
const existing = await readFile(jobFile, 'utf8');
|
|
256
|
+
return existing;
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
throw new Error('Failed to create job state');
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// Add to queue
|
|
263
|
+
const seq = ++this.#sequence;
|
|
264
|
+
const queueFile = join(this.#queuePath, `${seq.toString().padStart(12, '0')}-${id}.msg`);
|
|
265
|
+
await writeFileAtomic(queueFile, message);
|
|
266
|
+
// Publish event
|
|
267
|
+
this.#eventEmitter.emit('event', id, 'queued');
|
|
268
|
+
// Notify waiters
|
|
269
|
+
await this.#notifyDequeueWaiters();
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
async dequeue(workerId, timeout) {
|
|
273
|
+
// Try to get a job immediately
|
|
274
|
+
const message = await this.#getNextQueueMessage(workerId);
|
|
275
|
+
if (message)
|
|
276
|
+
return message;
|
|
277
|
+
// Wait for a job
|
|
278
|
+
return new Promise((resolve) => {
|
|
279
|
+
const timeoutId = setTimeout(() => {
|
|
280
|
+
const index = this.#dequeueWaiters.findIndex((w) => w.resolve === resolve);
|
|
281
|
+
if (index !== -1) {
|
|
282
|
+
this.#dequeueWaiters.splice(index, 1);
|
|
283
|
+
}
|
|
284
|
+
resolve(null);
|
|
285
|
+
}, timeout * 1000);
|
|
286
|
+
this.#dequeueWaiters.push({ workerId, resolve, timeoutId });
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
async requeue(id, message, workerId) {
|
|
290
|
+
// Remove from processing queue
|
|
291
|
+
const processingFile = join(this.#processingPath, workerId, `${id}.msg`);
|
|
292
|
+
await unlink(processingFile).catch(() => { });
|
|
293
|
+
// Add back to front of queue
|
|
294
|
+
const seq = ++this.#sequence;
|
|
295
|
+
const queueFile = join(this.#queuePath, `${seq.toString().padStart(12, '0')}-${id}.msg`);
|
|
296
|
+
await writeFileAtomic(queueFile, message);
|
|
297
|
+
// Notify waiters
|
|
298
|
+
await this.#notifyDequeueWaiters();
|
|
299
|
+
}
|
|
300
|
+
async ack(id, message, workerId) {
|
|
301
|
+
const processingFile = join(this.#processingPath, workerId, `${id}.msg`);
|
|
302
|
+
await unlink(processingFile).catch(() => { });
|
|
303
|
+
}
|
|
304
|
+
async getJobState(id) {
|
|
305
|
+
try {
|
|
306
|
+
return await readFile(join(this.#jobsPath, `${id}.state`), 'utf8');
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
async setJobState(id, state) {
|
|
313
|
+
await writeFileAtomic(join(this.#jobsPath, `${id}.state`), state);
|
|
314
|
+
}
|
|
315
|
+
async deleteJob(id) {
|
|
316
|
+
try {
|
|
317
|
+
await unlink(join(this.#jobsPath, `${id}.state`));
|
|
318
|
+
this.#eventEmitter.emit('event', id, 'cancelled');
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
async getJobStates(ids) {
|
|
326
|
+
const result = new Map();
|
|
327
|
+
await Promise.all(ids.map(async (id) => {
|
|
328
|
+
result.set(id, await this.getJobState(id));
|
|
329
|
+
}));
|
|
330
|
+
return result;
|
|
331
|
+
}
|
|
332
|
+
async setResult(id, result, ttlMs) {
|
|
333
|
+
const filePath = join(this.#resultsPath, `${id}.result`);
|
|
334
|
+
// Store TTL expiry time in a companion file
|
|
335
|
+
const ttlPath = join(this.#resultsPath, `${id}.ttl`);
|
|
336
|
+
const expiresAt = Date.now() + ttlMs;
|
|
337
|
+
await Promise.all([
|
|
338
|
+
writeFileAtomic(filePath, result),
|
|
339
|
+
writeFileAtomic(ttlPath, expiresAt.toString()),
|
|
340
|
+
]);
|
|
341
|
+
}
|
|
342
|
+
async getResult(id) {
|
|
343
|
+
try {
|
|
344
|
+
const ttlPath = join(this.#resultsPath, `${id}.ttl`);
|
|
345
|
+
const expiresAt = parseInt(await readFile(ttlPath, 'utf8'), 10);
|
|
346
|
+
if (Date.now() > expiresAt) {
|
|
347
|
+
// Expired - delete files
|
|
348
|
+
await Promise.all([
|
|
349
|
+
unlink(join(this.#resultsPath, `${id}.result`)).catch(() => { }),
|
|
350
|
+
unlink(ttlPath).catch(() => { }),
|
|
351
|
+
]);
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
return await readFile(join(this.#resultsPath, `${id}.result`));
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
async setError(id, error, ttlMs) {
|
|
361
|
+
const filePath = join(this.#errorsPath, `${id}.error`);
|
|
362
|
+
const ttlPath = join(this.#errorsPath, `${id}.ttl`);
|
|
363
|
+
const expiresAt = Date.now() + ttlMs;
|
|
364
|
+
await Promise.all([
|
|
365
|
+
writeFileAtomic(filePath, error),
|
|
366
|
+
writeFileAtomic(ttlPath, expiresAt.toString()),
|
|
367
|
+
]);
|
|
368
|
+
}
|
|
369
|
+
async getError(id) {
|
|
370
|
+
try {
|
|
371
|
+
const ttlPath = join(this.#errorsPath, `${id}.ttl`);
|
|
372
|
+
const expiresAt = parseInt(await readFile(ttlPath, 'utf8'), 10);
|
|
373
|
+
if (Date.now() > expiresAt) {
|
|
374
|
+
await Promise.all([
|
|
375
|
+
unlink(join(this.#errorsPath, `${id}.error`)).catch(() => { }),
|
|
376
|
+
unlink(ttlPath).catch(() => { }),
|
|
377
|
+
]);
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
return await readFile(join(this.#errorsPath, `${id}.error`));
|
|
381
|
+
}
|
|
382
|
+
catch {
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
async registerWorker(workerId, ttlMs) {
|
|
387
|
+
const filePath = join(this.#workersPath, `${workerId}.worker`);
|
|
388
|
+
const expiresAt = Date.now() + ttlMs;
|
|
389
|
+
await writeFileAtomic(filePath, expiresAt.toString());
|
|
390
|
+
}
|
|
391
|
+
async refreshWorker(workerId, ttlMs) {
|
|
392
|
+
await this.registerWorker(workerId, ttlMs);
|
|
393
|
+
}
|
|
394
|
+
async unregisterWorker(workerId) {
|
|
395
|
+
await unlink(join(this.#workersPath, `${workerId}.worker`)).catch(() => { });
|
|
396
|
+
// Also clean up processing queue
|
|
397
|
+
await rm(join(this.#processingPath, workerId), {
|
|
398
|
+
recursive: true,
|
|
399
|
+
force: true,
|
|
400
|
+
}).catch(() => { });
|
|
401
|
+
}
|
|
402
|
+
async getWorkers() {
|
|
403
|
+
try {
|
|
404
|
+
const files = await readdir(this.#workersPath);
|
|
405
|
+
const now = Date.now();
|
|
406
|
+
const workers = [];
|
|
407
|
+
for (const file of files) {
|
|
408
|
+
if (!file.endsWith('.worker'))
|
|
409
|
+
continue;
|
|
410
|
+
const workerId = file.replace('.worker', '');
|
|
411
|
+
try {
|
|
412
|
+
const expiresAt = parseInt(await readFile(join(this.#workersPath, file), 'utf8'), 10);
|
|
413
|
+
if (now <= expiresAt) {
|
|
414
|
+
workers.push(workerId);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
catch {
|
|
418
|
+
// Ignore unreadable files
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return workers;
|
|
422
|
+
}
|
|
423
|
+
catch {
|
|
424
|
+
return [];
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
async getProcessingJobs(workerId) {
|
|
428
|
+
const processingDir = join(this.#processingPath, workerId);
|
|
429
|
+
try {
|
|
430
|
+
const files = await readdir(processingDir);
|
|
431
|
+
const jobs = [];
|
|
432
|
+
for (const file of files) {
|
|
433
|
+
if (!file.endsWith('.msg'))
|
|
434
|
+
continue;
|
|
435
|
+
try {
|
|
436
|
+
const content = await readFile(join(processingDir, file));
|
|
437
|
+
jobs.push(content);
|
|
438
|
+
}
|
|
439
|
+
catch {
|
|
440
|
+
// Ignore unreadable files
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return jobs;
|
|
444
|
+
}
|
|
445
|
+
catch {
|
|
446
|
+
return [];
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
async subscribeToJob(id, handler) {
|
|
450
|
+
const eventName = `notify:${id}`;
|
|
451
|
+
this.#notifyEmitter.on(eventName, handler);
|
|
452
|
+
return async () => {
|
|
453
|
+
this.#notifyEmitter.off(eventName, handler);
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
async notifyJobComplete(id, status) {
|
|
457
|
+
// Write a notification file that will be picked up by the watcher
|
|
458
|
+
const notifyFile = join(this.#notifyPath, `${id}-${Date.now()}.notify`);
|
|
459
|
+
await writeFileAtomic(notifyFile, `${id}:${status}`);
|
|
460
|
+
// Also emit locally for in-process subscribers
|
|
461
|
+
this.#notifyEmitter.emit(`notify:${id}`, status);
|
|
462
|
+
}
|
|
463
|
+
async subscribeToEvents(handler) {
|
|
464
|
+
this.#eventEmitter.on('event', handler);
|
|
465
|
+
return async () => {
|
|
466
|
+
this.#eventEmitter.off('event', handler);
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
async publishEvent(id, event) {
|
|
470
|
+
this.#eventEmitter.emit('event', id, event);
|
|
471
|
+
}
|
|
472
|
+
async completeJob(id, message, workerId, result, resultTtlMs) {
|
|
473
|
+
const timestamp = Date.now();
|
|
474
|
+
// Set state to completed
|
|
475
|
+
await this.setJobState(id, `completed:${timestamp}`);
|
|
476
|
+
// Store result
|
|
477
|
+
await this.setResult(id, result, resultTtlMs);
|
|
478
|
+
// Remove from processing queue
|
|
479
|
+
await this.ack(id, message, workerId);
|
|
480
|
+
// Publish notification
|
|
481
|
+
await this.notifyJobComplete(id, 'completed');
|
|
482
|
+
// Publish event
|
|
483
|
+
this.#eventEmitter.emit('event', id, 'completed');
|
|
484
|
+
}
|
|
485
|
+
async failJob(id, message, workerId, error, errorTtlMs) {
|
|
486
|
+
const timestamp = Date.now();
|
|
487
|
+
// Set state to failed
|
|
488
|
+
await this.setJobState(id, `failed:${timestamp}`);
|
|
489
|
+
// Store error
|
|
490
|
+
await this.setError(id, error, errorTtlMs);
|
|
491
|
+
// Remove from processing queue
|
|
492
|
+
await this.ack(id, message, workerId);
|
|
493
|
+
// Publish notification
|
|
494
|
+
await this.notifyJobComplete(id, 'failed');
|
|
495
|
+
// Publish event
|
|
496
|
+
this.#eventEmitter.emit('event', id, 'failed');
|
|
497
|
+
}
|
|
498
|
+
async retryJob(id, message, workerId, attempts) {
|
|
499
|
+
const timestamp = Date.now();
|
|
500
|
+
// Set state to failing
|
|
501
|
+
await this.setJobState(id, `failing:${timestamp}:${attempts}`);
|
|
502
|
+
// Move from processing queue to main queue
|
|
503
|
+
await this.requeue(id, message, workerId);
|
|
504
|
+
// Publish notification
|
|
505
|
+
await this.notifyJobComplete(id, 'failing');
|
|
506
|
+
// Publish event
|
|
507
|
+
this.#eventEmitter.emit('event', id, 'failing');
|
|
508
|
+
}
|
|
509
|
+
async #cleanupExpired() {
|
|
510
|
+
const now = Date.now();
|
|
511
|
+
// Clean expired results
|
|
512
|
+
try {
|
|
513
|
+
const resultFiles = await readdir(this.#resultsPath);
|
|
514
|
+
for (const file of resultFiles) {
|
|
515
|
+
if (!file.endsWith('.ttl'))
|
|
516
|
+
continue;
|
|
517
|
+
const id = file.replace('.ttl', '');
|
|
518
|
+
try {
|
|
519
|
+
const expiresAt = parseInt(await readFile(join(this.#resultsPath, file), 'utf8'), 10);
|
|
520
|
+
if (now > expiresAt) {
|
|
521
|
+
await unlink(join(this.#resultsPath, `${id}.result`)).catch(() => { });
|
|
522
|
+
await unlink(join(this.#resultsPath, file)).catch(() => { });
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
catch {
|
|
526
|
+
// Ignore errors
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
catch {
|
|
531
|
+
// Ignore errors
|
|
532
|
+
}
|
|
533
|
+
// Clean expired errors
|
|
534
|
+
try {
|
|
535
|
+
const errorFiles = await readdir(this.#errorsPath);
|
|
536
|
+
for (const file of errorFiles) {
|
|
537
|
+
if (!file.endsWith('.ttl'))
|
|
538
|
+
continue;
|
|
539
|
+
const id = file.replace('.ttl', '');
|
|
540
|
+
try {
|
|
541
|
+
const expiresAt = parseInt(await readFile(join(this.#errorsPath, file), 'utf8'), 10);
|
|
542
|
+
if (now > expiresAt) {
|
|
543
|
+
await unlink(join(this.#errorsPath, `${id}.error`)).catch(() => { });
|
|
544
|
+
await unlink(join(this.#errorsPath, file)).catch(() => { });
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
catch {
|
|
548
|
+
// Ignore errors
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
catch {
|
|
553
|
+
// Ignore errors
|
|
554
|
+
}
|
|
555
|
+
// Clean expired workers
|
|
556
|
+
try {
|
|
557
|
+
const workerFiles = await readdir(this.#workersPath);
|
|
558
|
+
for (const file of workerFiles) {
|
|
559
|
+
if (!file.endsWith('.worker'))
|
|
560
|
+
continue;
|
|
561
|
+
try {
|
|
562
|
+
const expiresAt = parseInt(await readFile(join(this.#workersPath, file), 'utf8'), 10);
|
|
563
|
+
if (now > expiresAt) {
|
|
564
|
+
await unlink(join(this.#workersPath, file)).catch(() => { });
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
catch {
|
|
568
|
+
// Ignore errors
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
catch {
|
|
573
|
+
// Ignore errors
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Clear all data (useful for testing)
|
|
578
|
+
*/
|
|
579
|
+
async clear() {
|
|
580
|
+
await Promise.all([
|
|
581
|
+
rm(this.#queuePath, { recursive: true, force: true }),
|
|
582
|
+
rm(this.#processingPath, { recursive: true, force: true }),
|
|
583
|
+
rm(this.#jobsPath, { recursive: true, force: true }),
|
|
584
|
+
rm(this.#resultsPath, { recursive: true, force: true }),
|
|
585
|
+
rm(this.#errorsPath, { recursive: true, force: true }),
|
|
586
|
+
rm(this.#workersPath, { recursive: true, force: true }),
|
|
587
|
+
rm(this.#notifyPath, { recursive: true, force: true }),
|
|
588
|
+
]);
|
|
589
|
+
// Recreate directories
|
|
590
|
+
await Promise.all([
|
|
591
|
+
mkdir(this.#queuePath, { recursive: true }),
|
|
592
|
+
mkdir(this.#processingPath, { recursive: true }),
|
|
593
|
+
mkdir(this.#jobsPath, { recursive: true }),
|
|
594
|
+
mkdir(this.#resultsPath, { recursive: true }),
|
|
595
|
+
mkdir(this.#errorsPath, { recursive: true }),
|
|
596
|
+
mkdir(this.#workersPath, { recursive: true }),
|
|
597
|
+
mkdir(this.#notifyPath, { recursive: true }),
|
|
598
|
+
]);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
//# sourceMappingURL=file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/storage/file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Storage } from './types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* In-memory storage implementation for testing and single-process scenarios
|
|
4
|
+
*/
|
|
5
|
+
export declare class MemoryStorage implements Storage {
|
|
6
|
+
#private;
|
|
7
|
+
constructor();
|
|
8
|
+
connect(): Promise<void>;
|
|
9
|
+
disconnect(): Promise<void>;
|
|
10
|
+
enqueue(id: string, message: Buffer, timestamp: number): Promise<string | null>;
|
|
11
|
+
dequeue(workerId: string, timeout: number): Promise<Buffer | null>;
|
|
12
|
+
requeue(id: string, message: Buffer, workerId: string): Promise<void>;
|
|
13
|
+
ack(id: string, message: Buffer, workerId: string): Promise<void>;
|
|
14
|
+
getJobState(id: string): Promise<string | null>;
|
|
15
|
+
setJobState(id: string, state: string): Promise<void>;
|
|
16
|
+
deleteJob(id: string): Promise<boolean>;
|
|
17
|
+
getJobStates(ids: string[]): Promise<Map<string, string | null>>;
|
|
18
|
+
setResult(id: string, result: Buffer, ttlMs: number): Promise<void>;
|
|
19
|
+
getResult(id: string): Promise<Buffer | null>;
|
|
20
|
+
setError(id: string, error: Buffer, ttlMs: number): Promise<void>;
|
|
21
|
+
getError(id: string): Promise<Buffer | null>;
|
|
22
|
+
registerWorker(workerId: string, ttlMs: number): Promise<void>;
|
|
23
|
+
refreshWorker(workerId: string, ttlMs: number): Promise<void>;
|
|
24
|
+
unregisterWorker(workerId: string): Promise<void>;
|
|
25
|
+
getWorkers(): Promise<string[]>;
|
|
26
|
+
getProcessingJobs(workerId: string): Promise<Buffer[]>;
|
|
27
|
+
subscribeToJob(id: string, handler: (status: 'completed' | 'failed' | 'failing') => void): Promise<() => Promise<void>>;
|
|
28
|
+
notifyJobComplete(id: string, status: 'completed' | 'failed' | 'failing'): Promise<void>;
|
|
29
|
+
subscribeToEvents(handler: (id: string, event: string) => void): Promise<() => Promise<void>>;
|
|
30
|
+
publishEvent(id: string, event: string): Promise<void>;
|
|
31
|
+
completeJob(id: string, message: Buffer, workerId: string, result: Buffer, resultTtlMs: number): Promise<void>;
|
|
32
|
+
failJob(id: string, message: Buffer, workerId: string, error: Buffer, errorTtlMs: number): Promise<void>;
|
|
33
|
+
retryJob(id: string, message: Buffer, workerId: string, attempts: number): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Clear all data (useful for testing)
|
|
36
|
+
*/
|
|
37
|
+
clear(): void;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=memory.d.ts.map
|