bunqueue 2.4.8 → 2.5.1

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 (61) hide show
  1. package/README.md +45 -1
  2. package/dist/infrastructure/backup/s3BackupOperations.d.ts.map +1 -1
  3. package/dist/infrastructure/backup/s3BackupOperations.js +3 -1
  4. package/dist/infrastructure/backup/s3BackupOperations.js.map +1 -1
  5. package/dist/mcp/adapter.d.ts +341 -0
  6. package/dist/mcp/adapter.d.ts.map +1 -0
  7. package/dist/mcp/adapter.js +695 -0
  8. package/dist/mcp/adapter.js.map +1 -0
  9. package/dist/mcp/index.d.ts +26 -4
  10. package/dist/mcp/index.d.ts.map +1 -1
  11. package/dist/mcp/index.js +68 -87
  12. package/dist/mcp/index.js.map +1 -1
  13. package/dist/mcp/resources.d.ts +8 -0
  14. package/dist/mcp/resources.d.ts.map +1 -0
  15. package/dist/mcp/resources.js +96 -0
  16. package/dist/mcp/resources.js.map +1 -0
  17. package/dist/mcp/tools/consumptionTools.d.ts +8 -0
  18. package/dist/mcp/tools/consumptionTools.d.ts.map +1 -0
  19. package/dist/mcp/tools/consumptionTools.js +95 -0
  20. package/dist/mcp/tools/consumptionTools.js.map +1 -0
  21. package/dist/mcp/tools/cronTools.d.ts +7 -0
  22. package/dist/mcp/tools/cronTools.d.ts.map +1 -0
  23. package/dist/mcp/tools/cronTools.js +52 -0
  24. package/dist/mcp/tools/cronTools.js.map +1 -0
  25. package/dist/mcp/tools/dlqTools.d.ts +7 -0
  26. package/dist/mcp/tools/dlqTools.d.ts.map +1 -0
  27. package/dist/mcp/tools/dlqTools.js +58 -0
  28. package/dist/mcp/tools/dlqTools.js.map +1 -0
  29. package/dist/mcp/tools/jobMgmtTools.d.ts +8 -0
  30. package/dist/mcp/tools/jobMgmtTools.d.ts.map +1 -0
  31. package/dist/mcp/tools/jobMgmtTools.js +62 -0
  32. package/dist/mcp/tools/jobMgmtTools.js.map +1 -0
  33. package/dist/mcp/tools/jobTools.d.ts +8 -0
  34. package/dist/mcp/tools/jobTools.d.ts.map +1 -0
  35. package/dist/mcp/tools/jobTools.js +115 -0
  36. package/dist/mcp/tools/jobTools.js.map +1 -0
  37. package/dist/mcp/tools/monitoringTools.d.ts +7 -0
  38. package/dist/mcp/tools/monitoringTools.d.ts.map +1 -0
  39. package/dist/mcp/tools/monitoringTools.js +93 -0
  40. package/dist/mcp/tools/monitoringTools.js.map +1 -0
  41. package/dist/mcp/tools/queueTools.d.ts +8 -0
  42. package/dist/mcp/tools/queueTools.d.ts.map +1 -0
  43. package/dist/mcp/tools/queueTools.js +126 -0
  44. package/dist/mcp/tools/queueTools.js.map +1 -0
  45. package/dist/mcp/tools/rateLimitTools.d.ts +7 -0
  46. package/dist/mcp/tools/rateLimitTools.d.ts.map +1 -0
  47. package/dist/mcp/tools/rateLimitTools.js +63 -0
  48. package/dist/mcp/tools/rateLimitTools.js.map +1 -0
  49. package/dist/mcp/tools/webhookTools.d.ts +7 -0
  50. package/dist/mcp/tools/webhookTools.d.ts.map +1 -0
  51. package/dist/mcp/tools/webhookTools.js +56 -0
  52. package/dist/mcp/tools/webhookTools.js.map +1 -0
  53. package/dist/mcp/tools/withErrorHandler.d.ts +21 -0
  54. package/dist/mcp/tools/withErrorHandler.d.ts.map +1 -0
  55. package/dist/mcp/tools/withErrorHandler.js +24 -0
  56. package/dist/mcp/tools/withErrorHandler.js.map +1 -0
  57. package/dist/mcp/tools/workerMgmtTools.d.ts +8 -0
  58. package/dist/mcp/tools/workerMgmtTools.d.ts.map +1 -0
  59. package/dist/mcp/tools/workerMgmtTools.js +33 -0
  60. package/dist/mcp/tools/workerMgmtTools.js.map +1 -0
  61. package/package.json +15 -13
@@ -0,0 +1,695 @@
1
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition, @typescript-eslint/no-unnecessary-type-conversion, @typescript-eslint/no-base-to-string, @typescript-eslint/prefer-readonly, @typescript-eslint/require-await */
2
+ /**
3
+ * MCP Backend Adapter
4
+ * Abstraction layer for embedded (SQLite direct) and TCP (remote server) modes.
5
+ */
6
+ import { jobId as toJobId } from '../domain/types/job';
7
+ /** Serialize a Job to a plain object */
8
+ function serializeJob(job) {
9
+ return {
10
+ id: String(job.id),
11
+ queue: job.queue,
12
+ data: job.data,
13
+ priority: job.priority,
14
+ progress: job.progress,
15
+ attempts: job.attempts,
16
+ maxAttempts: job.maxAttempts,
17
+ createdAt: new Date(job.createdAt).toISOString(),
18
+ startedAt: job.startedAt ? new Date(job.startedAt).toISOString() : undefined,
19
+ };
20
+ }
21
+ function serializeCron(c) {
22
+ return {
23
+ name: c.name,
24
+ queue: c.queue,
25
+ schedule: c.schedule ?? undefined,
26
+ repeatEvery: c.repeatEvery ?? undefined,
27
+ nextRun: c.nextRun ? new Date(c.nextRun).toISOString() : null,
28
+ executions: c.executions,
29
+ };
30
+ }
31
+ // ============ Embedded Backend ============
32
+ import { getSharedManager, shutdownManager } from '../client/manager';
33
+ export class EmbeddedBackend {
34
+ get manager() {
35
+ return getSharedManager();
36
+ }
37
+ async addJob(queue, name, data, opts) {
38
+ const job = await this.manager.push(queue, {
39
+ data: { name, ...data },
40
+ priority: opts?.priority,
41
+ delay: opts?.delay,
42
+ maxAttempts: opts?.attempts,
43
+ });
44
+ return { jobId: String(job.id) };
45
+ }
46
+ async addJobsBulk(queue, jobs) {
47
+ const inputs = jobs.map((j) => ({
48
+ data: { name: j.name, ...j.data },
49
+ priority: j.priority,
50
+ delay: j.delay,
51
+ }));
52
+ const ids = await this.manager.pushBatch(queue, inputs);
53
+ return { jobIds: ids.map(String) };
54
+ }
55
+ async getJob(id) {
56
+ const job = await this.manager.getJob(toJobId(id));
57
+ return job ? serializeJob(job) : null;
58
+ }
59
+ getJobState(id) {
60
+ return Promise.resolve(this.manager.getJobState(toJobId(id)));
61
+ }
62
+ getJobResult(id) {
63
+ return Promise.resolve(this.manager.getResult(toJobId(id)));
64
+ }
65
+ cancelJob(id) {
66
+ return Promise.resolve(this.manager.cancel(toJobId(id)));
67
+ }
68
+ promoteJob(id) {
69
+ return Promise.resolve(this.manager.promote(toJobId(id)));
70
+ }
71
+ updateProgress(id, progress, message) {
72
+ return Promise.resolve(this.manager.updateProgress(toJobId(id), progress, message));
73
+ }
74
+ updateJobData(id, data) {
75
+ return Promise.resolve(this.manager.updateJobData(toJobId(id), data));
76
+ }
77
+ changeJobPriority(id, priority) {
78
+ return Promise.resolve(this.manager.changePriority(toJobId(id), priority));
79
+ }
80
+ moveToDelayed(id, delay) {
81
+ return Promise.resolve(this.manager.moveToDelayed(toJobId(id), delay));
82
+ }
83
+ discardJob(id) {
84
+ return Promise.resolve(this.manager.discard(toJobId(id)));
85
+ }
86
+ getChildrenValues(parentJobId) {
87
+ return Promise.resolve(this.manager.getChildrenValues(toJobId(parentJobId)));
88
+ }
89
+ getJobByCustomId(customId) {
90
+ const job = this.manager.getJobByCustomId(customId);
91
+ return Promise.resolve(job ? serializeJob(job) : null);
92
+ }
93
+ waitForJobCompletion(id, timeoutMs) {
94
+ return this.manager.waitForJobCompletion(toJobId(id), timeoutMs);
95
+ }
96
+ async pullJob(queue, timeoutMs) {
97
+ const job = await this.manager.pull(queue, timeoutMs);
98
+ return job ? serializeJob(job) : null;
99
+ }
100
+ async pullJobBatch(queue, count, timeoutMs) {
101
+ const jobs = await this.manager.pullBatch(queue, count, timeoutMs);
102
+ return jobs.map(serializeJob);
103
+ }
104
+ async ackJob(id, result) {
105
+ await this.manager.ack(toJobId(id), result);
106
+ }
107
+ async ackJobBatch(ids) {
108
+ await this.manager.ackBatch(ids.map(toJobId));
109
+ }
110
+ async failJob(id, error) {
111
+ await this.manager.fail(toJobId(id), error);
112
+ }
113
+ jobHeartbeat(id) {
114
+ return Promise.resolve(this.manager.jobHeartbeat(toJobId(id)));
115
+ }
116
+ jobHeartbeatBatch(ids) {
117
+ return Promise.resolve(this.manager.jobHeartbeatBatch(ids.map(toJobId)));
118
+ }
119
+ getProgress(id) {
120
+ return Promise.resolve(this.manager.getProgress(toJobId(id)));
121
+ }
122
+ changeDelay(id, delay) {
123
+ return Promise.resolve(this.manager.changeDelay(toJobId(id), delay));
124
+ }
125
+ extendLock(id, token, duration) {
126
+ return Promise.resolve(this.manager.extendLock(toJobId(id), token, duration));
127
+ }
128
+ getJobs(queue, opts) {
129
+ const jobs = this.manager.getJobs(queue, {
130
+ state: opts?.state,
131
+ start: opts?.start,
132
+ end: opts?.end,
133
+ });
134
+ return Promise.resolve(jobs.map(serializeJob));
135
+ }
136
+ getJobCounts(queue) {
137
+ return Promise.resolve(this.manager.getQueueJobCounts(queue));
138
+ }
139
+ pauseQueue(queue) {
140
+ this.manager.pause(queue);
141
+ return Promise.resolve();
142
+ }
143
+ resumeQueue(queue) {
144
+ this.manager.resume(queue);
145
+ return Promise.resolve();
146
+ }
147
+ drainQueue(queue) {
148
+ return Promise.resolve(this.manager.drain(queue));
149
+ }
150
+ obliterateQueue(queue) {
151
+ this.manager.obliterate(queue);
152
+ return Promise.resolve();
153
+ }
154
+ listQueues() {
155
+ return Promise.resolve(this.manager.listQueues());
156
+ }
157
+ countJobs(queue) {
158
+ return Promise.resolve(this.manager.count(queue));
159
+ }
160
+ cleanQueue(queue, graceMs, state, limit) {
161
+ return Promise.resolve(this.manager.clean(queue, graceMs, state, limit));
162
+ }
163
+ isPaused(queue) {
164
+ return Promise.resolve(this.manager.isPaused(queue));
165
+ }
166
+ getCountsPerPriority(queue) {
167
+ return Promise.resolve(this.manager.getCountsPerPriority(queue));
168
+ }
169
+ getDlq(queue, limit) {
170
+ return Promise.resolve(this.manager.getDlq(queue, limit).map(serializeJob));
171
+ }
172
+ retryDlq(queue, id) {
173
+ return Promise.resolve(this.manager.retryDlq(queue, id ? toJobId(id) : undefined));
174
+ }
175
+ purgeDlq(queue) {
176
+ return Promise.resolve(this.manager.purgeDlq(queue));
177
+ }
178
+ retryCompleted(queue, id) {
179
+ return Promise.resolve(this.manager.retryCompleted(queue, id ? toJobId(id) : undefined));
180
+ }
181
+ setRateLimit(queue, limit) {
182
+ this.manager.setRateLimit(queue, limit);
183
+ return Promise.resolve();
184
+ }
185
+ clearRateLimit(queue) {
186
+ this.manager.clearRateLimit(queue);
187
+ return Promise.resolve();
188
+ }
189
+ setConcurrency(queue, limit) {
190
+ this.manager.setConcurrency(queue, limit);
191
+ return Promise.resolve();
192
+ }
193
+ clearConcurrency(queue) {
194
+ this.manager.clearConcurrency(queue);
195
+ return Promise.resolve();
196
+ }
197
+ addCron(input) {
198
+ const cron = this.manager.addCron(input);
199
+ return Promise.resolve(serializeCron(cron));
200
+ }
201
+ listCrons() {
202
+ return Promise.resolve(this.manager.listCrons().map(serializeCron));
203
+ }
204
+ getCron(name) {
205
+ const cron = this.manager.getCron(name);
206
+ return Promise.resolve(cron ? serializeCron(cron) : null);
207
+ }
208
+ deleteCron(name) {
209
+ return Promise.resolve(this.manager.removeCron(name));
210
+ }
211
+ addWebhook(url, events, queue) {
212
+ const wh = this.manager.webhookManager.add(url, events, queue);
213
+ return Promise.resolve({
214
+ id: String(wh.id),
215
+ url: wh.url,
216
+ events: wh.events,
217
+ queue: wh.queue ?? undefined,
218
+ enabled: wh.enabled,
219
+ });
220
+ }
221
+ removeWebhook(id) {
222
+ return Promise.resolve(this.manager.webhookManager.remove(id));
223
+ }
224
+ listWebhooks() {
225
+ return Promise.resolve(this.manager.webhookManager.list().map((wh) => ({
226
+ id: String(wh.id),
227
+ url: wh.url,
228
+ events: wh.events,
229
+ queue: wh.queue ?? undefined,
230
+ enabled: wh.enabled,
231
+ })));
232
+ }
233
+ setWebhookEnabled(id, enabled) {
234
+ return Promise.resolve(this.manager.webhookManager.setEnabled(id, enabled));
235
+ }
236
+ registerWorker(name, queues) {
237
+ const w = this.manager.workerManager.register(name, queues);
238
+ return Promise.resolve({
239
+ id: String(w.id),
240
+ name: w.name,
241
+ queues: w.queues,
242
+ active: w.activeJobs,
243
+ processed: w.processedJobs,
244
+ failed: w.failedJobs,
245
+ lastHeartbeat: w.lastSeen,
246
+ });
247
+ }
248
+ unregisterWorker(id) {
249
+ return Promise.resolve(this.manager.workerManager.unregister(id));
250
+ }
251
+ workerHeartbeat(id) {
252
+ return Promise.resolve(this.manager.workerManager.heartbeat(id));
253
+ }
254
+ getStats() {
255
+ const stats = this.manager.getStats();
256
+ return Promise.resolve(JSON.parse(JSON.stringify(stats, (_key, value) => typeof value === 'bigint' ? Number(value) : value)));
257
+ }
258
+ listWorkers() {
259
+ return Promise.resolve(this.manager.workerManager.list().map((w) => ({
260
+ id: String(w.id),
261
+ name: w.name,
262
+ queues: w.queues,
263
+ active: w.activeJobs,
264
+ processed: w.processedJobs,
265
+ failed: w.failedJobs,
266
+ lastHeartbeat: w.lastSeen,
267
+ })));
268
+ }
269
+ getJobLogs(id) {
270
+ return Promise.resolve(this.manager.getLogs(toJobId(id)));
271
+ }
272
+ addJobLog(id, message, level) {
273
+ return Promise.resolve(this.manager.addLog(toJobId(id), message, level));
274
+ }
275
+ getPerQueueStats() {
276
+ const stats = this.manager.getPerQueueStats();
277
+ const result = {};
278
+ for (const [k, v] of stats)
279
+ result[k] = v;
280
+ return Promise.resolve(result);
281
+ }
282
+ getMemoryStats() {
283
+ return Promise.resolve(this.manager.getMemoryStats());
284
+ }
285
+ getPrometheusMetrics() {
286
+ return Promise.resolve(this.manager.getPrometheusMetrics());
287
+ }
288
+ getStorageStatus() {
289
+ const status = this.manager.getStorageStatus();
290
+ return Promise.resolve({ diskFull: status.diskFull, error: status.error });
291
+ }
292
+ clearJobLogs(id, keepLogs) {
293
+ this.manager.clearLogs(toJobId(id), keepLogs);
294
+ return Promise.resolve();
295
+ }
296
+ compactMemory() {
297
+ this.manager.compactMemory();
298
+ return Promise.resolve();
299
+ }
300
+ shutdown() {
301
+ shutdownManager();
302
+ }
303
+ }
304
+ // ============ TCP Backend ============
305
+ import { TcpConnectionPool } from '../client/tcpPool';
306
+ export class TcpBackend {
307
+ pool;
308
+ constructor(opts) {
309
+ this.pool = new TcpConnectionPool({
310
+ host: opts.host ?? 'localhost',
311
+ port: opts.port ?? 6789,
312
+ token: opts.token,
313
+ poolSize: 2,
314
+ });
315
+ }
316
+ async connect() {
317
+ await this.pool.connect();
318
+ }
319
+ async send(cmd) {
320
+ return this.pool.send(cmd);
321
+ }
322
+ parseJob(j) {
323
+ return {
324
+ id: String(j.id),
325
+ queue: j.queue ?? '',
326
+ data: j.data,
327
+ priority: j.priority ?? 0,
328
+ progress: j.progress ?? 0,
329
+ attempts: j.attempts ?? 0,
330
+ maxAttempts: j.maxAttempts ?? 3,
331
+ createdAt: j.createdAt
332
+ ? new Date(j.createdAt).toISOString()
333
+ : new Date().toISOString(),
334
+ startedAt: j.startedAt ? new Date(j.startedAt).toISOString() : undefined,
335
+ };
336
+ }
337
+ async addJob(queue, name, data, opts) {
338
+ const res = await this.send({
339
+ cmd: 'PUSH',
340
+ queue,
341
+ data: { name, ...data },
342
+ priority: opts?.priority,
343
+ delay: opts?.delay,
344
+ maxAttempts: opts?.attempts,
345
+ });
346
+ return { jobId: String(res.id) };
347
+ }
348
+ async addJobsBulk(queue, jobs) {
349
+ const res = await this.send({
350
+ cmd: 'PUSHB',
351
+ queue,
352
+ jobs: jobs.map((j) => ({
353
+ data: { name: j.name, ...j.data },
354
+ priority: j.priority,
355
+ delay: j.delay,
356
+ })),
357
+ });
358
+ return { jobIds: (res.ids ?? []).map(String) };
359
+ }
360
+ async getJob(id) {
361
+ const res = await this.send({ cmd: 'GetJob', id });
362
+ if (!res.job)
363
+ return null;
364
+ return this.parseJob(res.job);
365
+ }
366
+ async getJobState(id) {
367
+ const res = await this.send({ cmd: 'GetState', id });
368
+ return res.state ?? 'unknown';
369
+ }
370
+ async getJobResult(id) {
371
+ const res = await this.send({ cmd: 'GetResult', id });
372
+ return res.result;
373
+ }
374
+ async cancelJob(id) {
375
+ const res = await this.send({ cmd: 'Cancel', id });
376
+ return res.ok ?? false;
377
+ }
378
+ async promoteJob(id) {
379
+ const res = await this.send({ cmd: 'Promote', id });
380
+ return res.ok ?? false;
381
+ }
382
+ async updateProgress(id, progress, message) {
383
+ const res = await this.send({ cmd: 'Progress', id, progress, message });
384
+ return res.ok ?? false;
385
+ }
386
+ async updateJobData(id, data) {
387
+ const res = await this.send({ cmd: 'Update', id, data });
388
+ return res.ok ?? false;
389
+ }
390
+ async changeJobPriority(id, priority) {
391
+ const res = await this.send({ cmd: 'ChangePriority', id, priority });
392
+ return res.ok ?? false;
393
+ }
394
+ async moveToDelayed(id, delay) {
395
+ const res = await this.send({ cmd: 'MoveToDelayed', id, delay });
396
+ return res.ok ?? false;
397
+ }
398
+ async discardJob(id) {
399
+ const res = await this.send({ cmd: 'Discard', id });
400
+ return res.ok ?? false;
401
+ }
402
+ async getChildrenValues(parentJobId) {
403
+ // TCP doesn't have a direct command for this; get job and iterate children
404
+ const res = await this.send({ cmd: 'GetJob', id: parentJobId });
405
+ if (!res.job)
406
+ return {};
407
+ const job = res.job;
408
+ const childrenIds = job.childrenIds ?? [];
409
+ const results = {};
410
+ for (const childId of childrenIds) {
411
+ const childRes = await this.send({ cmd: 'GetResult', id: childId });
412
+ if (childRes.result !== undefined) {
413
+ const childJob = await this.send({ cmd: 'GetJob', id: childId });
414
+ const queue = childJob.job?.queue ?? '';
415
+ results[`${queue}:${childId}`] = childRes.result;
416
+ }
417
+ }
418
+ return results;
419
+ }
420
+ async getJobByCustomId(customId) {
421
+ const res = await this.send({ cmd: 'GetJobByCustomId', customId });
422
+ if (!res.job)
423
+ return null;
424
+ return this.parseJob(res.job);
425
+ }
426
+ async waitForJobCompletion(id, timeoutMs) {
427
+ const res = await this.send({ cmd: 'WaitJob', id, timeout: timeoutMs });
428
+ return res.ok ?? false;
429
+ }
430
+ async getProgress(id) {
431
+ const res = await this.send({ cmd: 'GetProgress', id });
432
+ if (res.progress === undefined)
433
+ return null;
434
+ return {
435
+ progress: res.progress ?? 0,
436
+ message: res.message ?? null,
437
+ };
438
+ }
439
+ async changeDelay(id, delay) {
440
+ const res = await this.send({ cmd: 'MoveToDelayed', id, delay });
441
+ return res.ok ?? false;
442
+ }
443
+ async extendLock(id, token, duration) {
444
+ const res = await this.send({ cmd: 'JobHeartbeat', id, token, duration });
445
+ return res.ok ?? false;
446
+ }
447
+ async pullJob(queue, timeoutMs) {
448
+ const res = await this.send({ cmd: 'PULL', queue, timeout: timeoutMs });
449
+ if (!res.job)
450
+ return null;
451
+ return this.parseJob(res.job);
452
+ }
453
+ async pullJobBatch(queue, count, timeoutMs) {
454
+ const res = await this.send({ cmd: 'PULLB', queue, count, timeout: timeoutMs });
455
+ return (res.jobs ?? []).map((j) => this.parseJob(j));
456
+ }
457
+ async ackJob(id, result) {
458
+ await this.send({ cmd: 'ACK', id, result });
459
+ }
460
+ async ackJobBatch(ids) {
461
+ await this.send({ cmd: 'ACKB', ids });
462
+ }
463
+ async failJob(id, error) {
464
+ await this.send({ cmd: 'FAIL', id, error });
465
+ }
466
+ async jobHeartbeat(id) {
467
+ const res = await this.send({ cmd: 'JobHeartbeat', id });
468
+ return res.ok ?? false;
469
+ }
470
+ async jobHeartbeatBatch(ids) {
471
+ const res = await this.send({ cmd: 'JobHeartbeatB', ids });
472
+ return res.count ?? 0;
473
+ }
474
+ async getJobs(queue, opts) {
475
+ const res = await this.send({ cmd: 'GetJobs', queue, ...opts });
476
+ return (res.jobs ?? []).map((j) => this.parseJob(j));
477
+ }
478
+ async getJobCounts(queue) {
479
+ const res = await this.send({ cmd: 'GetJobCounts', queue });
480
+ return {
481
+ waiting: res.waiting ?? 0,
482
+ delayed: res.delayed ?? 0,
483
+ active: res.active ?? 0,
484
+ completed: res.completed ?? 0,
485
+ failed: res.failed ?? 0,
486
+ };
487
+ }
488
+ async pauseQueue(queue) {
489
+ await this.send({ cmd: 'Pause', queue });
490
+ }
491
+ async resumeQueue(queue) {
492
+ await this.send({ cmd: 'Resume', queue });
493
+ }
494
+ async drainQueue(queue) {
495
+ const res = await this.send({ cmd: 'Drain', queue });
496
+ return res.removed ?? 0;
497
+ }
498
+ async obliterateQueue(queue) {
499
+ await this.send({ cmd: 'Obliterate', queue });
500
+ }
501
+ async listQueues() {
502
+ const res = await this.send({ cmd: 'ListQueues' });
503
+ return res.queues ?? [];
504
+ }
505
+ async countJobs(queue) {
506
+ const res = await this.send({ cmd: 'Count', queue });
507
+ return res.count ?? 0;
508
+ }
509
+ async cleanQueue(queue, graceMs, state, limit) {
510
+ const res = await this.send({ cmd: 'Clean', queue, grace: graceMs, state, limit });
511
+ return res.removed ?? 0;
512
+ }
513
+ async isPaused(queue) {
514
+ const res = await this.send({ cmd: 'IsPaused', queue });
515
+ return res.paused ?? false;
516
+ }
517
+ async getCountsPerPriority(queue) {
518
+ const res = await this.send({ cmd: 'GetCountsPerPriority', queue });
519
+ return res.counts ?? {};
520
+ }
521
+ async getDlq(queue, limit) {
522
+ const res = await this.send({ cmd: 'Dlq', queue, count: limit });
523
+ return (res.jobs ?? []).map((j) => this.parseJob(j));
524
+ }
525
+ async retryDlq(queue, id) {
526
+ const res = await this.send({ cmd: 'RetryDlq', queue, id });
527
+ return res.retried ?? 0;
528
+ }
529
+ async purgeDlq(queue) {
530
+ const res = await this.send({ cmd: 'PurgeDlq', queue });
531
+ return res.purged ?? 0;
532
+ }
533
+ async retryCompleted(queue, id) {
534
+ const res = await this.send({ cmd: 'RetryCompleted', queue, id });
535
+ return res.retried ?? 0;
536
+ }
537
+ async setRateLimit(queue, limit) {
538
+ await this.send({ cmd: 'RateLimit', queue, limit });
539
+ }
540
+ async clearRateLimit(queue) {
541
+ await this.send({ cmd: 'RateLimitClear', queue });
542
+ }
543
+ async setConcurrency(queue, limit) {
544
+ await this.send({ cmd: 'SetConcurrency', queue, limit });
545
+ }
546
+ async clearConcurrency(queue) {
547
+ await this.send({ cmd: 'ClearConcurrency', queue });
548
+ }
549
+ async addCron(input) {
550
+ const res = await this.send({ cmd: 'Cron', ...input });
551
+ return {
552
+ name: input.name,
553
+ queue: input.queue,
554
+ schedule: input.schedule ?? undefined,
555
+ repeatEvery: input.repeatEvery ?? undefined,
556
+ nextRun: res.nextRun ? new Date(res.nextRun).toISOString() : null,
557
+ executions: 0,
558
+ };
559
+ }
560
+ async listCrons() {
561
+ const res = await this.send({ cmd: 'CronList' });
562
+ return (res.crons ?? []).map((c) => ({
563
+ name: c.name,
564
+ queue: c.queue,
565
+ schedule: c.schedule,
566
+ repeatEvery: c.repeatEvery,
567
+ nextRun: c.nextRun ? new Date(c.nextRun).toISOString() : null,
568
+ executions: c.executions ?? 0,
569
+ }));
570
+ }
571
+ async getCron(name) {
572
+ const res = await this.send({ cmd: 'CronList' });
573
+ const crons = res.crons ?? [];
574
+ const c = crons.find((cr) => cr.name === name);
575
+ if (!c)
576
+ return null;
577
+ return {
578
+ name: c.name,
579
+ queue: c.queue,
580
+ schedule: c.schedule,
581
+ repeatEvery: c.repeatEvery,
582
+ nextRun: c.nextRun ? new Date(c.nextRun).toISOString() : null,
583
+ executions: c.executions ?? 0,
584
+ };
585
+ }
586
+ async deleteCron(name) {
587
+ const res = await this.send({ cmd: 'CronDelete', name });
588
+ return res.ok ?? true;
589
+ }
590
+ async addWebhook(url, events, queue) {
591
+ const res = await this.send({ cmd: 'AddWebhook', url, events, queue });
592
+ return { id: String(res.id ?? '0'), url, events, queue, enabled: true };
593
+ }
594
+ async removeWebhook(id) {
595
+ const res = await this.send({ cmd: 'RemoveWebhook', id });
596
+ return res.ok ?? true;
597
+ }
598
+ async listWebhooks() {
599
+ const res = await this.send({ cmd: 'ListWebhooks' });
600
+ return (res.webhooks ?? []).map((wh) => ({
601
+ id: String(wh.id),
602
+ url: wh.url,
603
+ events: wh.events ?? [],
604
+ queue: wh.queue,
605
+ enabled: wh.enabled ?? true,
606
+ }));
607
+ }
608
+ async getStats() {
609
+ return this.send({ cmd: 'Stats' });
610
+ }
611
+ async listWorkers() {
612
+ const res = await this.send({ cmd: 'ListWorkers' });
613
+ return (res.workers ?? []).map((w) => ({
614
+ id: String(w.id),
615
+ name: w.name,
616
+ queues: w.queues ?? [],
617
+ active: w.activeJobs ?? 0,
618
+ processed: w.processed ?? 0,
619
+ failed: w.failed ?? 0,
620
+ lastHeartbeat: w.lastHeartbeat ?? 0,
621
+ }));
622
+ }
623
+ async getJobLogs(id) {
624
+ const res = await this.send({ cmd: 'GetLogs', id });
625
+ return res.logs ?? [];
626
+ }
627
+ async addJobLog(id, message, level) {
628
+ const res = await this.send({ cmd: 'AddLog', id, message, level });
629
+ return res.ok ?? true;
630
+ }
631
+ async setWebhookEnabled(id, enabled) {
632
+ const res = await this.send({ cmd: 'SetWebhookEnabled', id, enabled });
633
+ return res.ok ?? true;
634
+ }
635
+ async registerWorker(name, queues) {
636
+ const res = await this.send({ cmd: 'RegisterWorker', name, queues });
637
+ return {
638
+ id: String(res.id ?? '0'),
639
+ name,
640
+ queues,
641
+ active: 0,
642
+ processed: 0,
643
+ failed: 0,
644
+ lastHeartbeat: Date.now(),
645
+ };
646
+ }
647
+ async unregisterWorker(id) {
648
+ const res = await this.send({ cmd: 'UnregisterWorker', id });
649
+ return res.ok ?? true;
650
+ }
651
+ async workerHeartbeat(id) {
652
+ const res = await this.send({ cmd: 'Heartbeat', id });
653
+ return res.ok ?? true;
654
+ }
655
+ async getPerQueueStats() {
656
+ const res = await this.send({ cmd: 'Metrics' });
657
+ return res.queues ?? res;
658
+ }
659
+ async getMemoryStats() {
660
+ const res = await this.send({ cmd: 'Stats' });
661
+ return res.memory ?? {};
662
+ }
663
+ async getPrometheusMetrics() {
664
+ const res = await this.send({ cmd: 'Prometheus' });
665
+ return res.metrics ?? '';
666
+ }
667
+ async clearJobLogs(id, _keepLogs) {
668
+ await this.send({ cmd: 'ClearLogs', id });
669
+ }
670
+ async compactMemory() {
671
+ await this.send({ cmd: 'CompactMemory' });
672
+ }
673
+ async getStorageStatus() {
674
+ // TCP mode doesn't have direct access to storage health; return healthy default
675
+ return { diskFull: false, error: null };
676
+ }
677
+ shutdown() {
678
+ this.pool.close();
679
+ }
680
+ }
681
+ /** Create backend based on environment configuration */
682
+ export async function createBackend() {
683
+ const mode = process.env.BUNQUEUE_MODE ?? 'embedded';
684
+ if (mode === 'tcp') {
685
+ const backend = new TcpBackend({
686
+ host: process.env.BUNQUEUE_HOST,
687
+ port: process.env.BUNQUEUE_PORT ? parseInt(process.env.BUNQUEUE_PORT, 10) : undefined,
688
+ token: process.env.BUNQUEUE_TOKEN,
689
+ });
690
+ await backend.connect();
691
+ return backend;
692
+ }
693
+ return new EmbeddedBackend();
694
+ }
695
+ //# sourceMappingURL=adapter.js.map