@basaltkit/queue 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/drivers/bullmq.d.ts +22 -0
- package/dist/drivers/bullmq.js +20 -1
- package/package.json +2 -2
package/dist/drivers/bullmq.d.ts
CHANGED
|
@@ -3,6 +3,26 @@ import type { AddJobOptions, JobExecutor, QueueDriver, QueueStats } from '../dri
|
|
|
3
3
|
export interface BullmqDriverOptions {
|
|
4
4
|
/** Redis URL (redis://... or rediss://...) or ioredis connection options. */
|
|
5
5
|
connection: string | ConnectionOptions;
|
|
6
|
+
/**
|
|
7
|
+
* Infra errors from BullMQ's Worker/Queue emitters (e.g. Redis down). BullMQ
|
|
8
|
+
* emits these as EventEmitter 'error' events — unhandled, they CRASH the
|
|
9
|
+
* process. Default: logged via console.error with full context — observable,
|
|
10
|
+
* never fatal, never silent. (Same pattern as realtime's onBridgeError.)
|
|
11
|
+
*/
|
|
12
|
+
onError?: (error: unknown, info: {
|
|
13
|
+
queue: string;
|
|
14
|
+
source: 'worker' | 'queue';
|
|
15
|
+
}) => void;
|
|
16
|
+
/**
|
|
17
|
+
* A job exhausted its retries (BullMQ 'failed'). Default: console.error —
|
|
18
|
+
* without this, exhausted jobs were only visible by polling queue stats.
|
|
19
|
+
*/
|
|
20
|
+
onJobFailed?: (info: {
|
|
21
|
+
queue: string;
|
|
22
|
+
job: string;
|
|
23
|
+
jobId?: string;
|
|
24
|
+
error: unknown;
|
|
25
|
+
}) => void;
|
|
6
26
|
}
|
|
7
27
|
export declare class BullmqQueueDriver implements QueueDriver {
|
|
8
28
|
readonly name = "bullmq";
|
|
@@ -16,6 +36,8 @@ export declare class BullmqQueueDriver implements QueueDriver {
|
|
|
16
36
|
private readonly queues;
|
|
17
37
|
private readonly workers;
|
|
18
38
|
private executor;
|
|
39
|
+
private readonly onError;
|
|
40
|
+
private readonly onJobFailed;
|
|
19
41
|
constructor(options: BullmqDriverOptions);
|
|
20
42
|
setExecutor(executor: JobExecutor): void;
|
|
21
43
|
add(queue: string, jobName: string, data: unknown, options: AddJobOptions): Promise<void>;
|
package/dist/drivers/bullmq.js
CHANGED
|
@@ -19,11 +19,19 @@ export class BullmqQueueDriver {
|
|
|
19
19
|
queues = new Map();
|
|
20
20
|
workers = [];
|
|
21
21
|
executor;
|
|
22
|
+
onError;
|
|
23
|
+
onJobFailed;
|
|
22
24
|
constructor(options) {
|
|
23
25
|
this.connection =
|
|
24
26
|
typeof options.connection === 'string'
|
|
25
27
|
? parseRedisUrl(options.connection)
|
|
26
28
|
: options.connection;
|
|
29
|
+
this.onError =
|
|
30
|
+
options.onError ??
|
|
31
|
+
((error, info) => console.error(`[basalt:queue] bullmq ${info.source} error (queue "${info.queue}"):`, error));
|
|
32
|
+
this.onJobFailed =
|
|
33
|
+
options.onJobFailed ??
|
|
34
|
+
((info) => console.error(`[basalt:queue] job "${info.job}"${info.jobId ? ` (id ${info.jobId})` : ''} on queue "${info.queue}" failed permanently:`, info.error));
|
|
27
35
|
}
|
|
28
36
|
setExecutor(executor) {
|
|
29
37
|
this.executor = executor;
|
|
@@ -41,10 +49,20 @@ export class BullmqQueueDriver {
|
|
|
41
49
|
});
|
|
42
50
|
}
|
|
43
51
|
startWorker(queue, options = {}) {
|
|
44
|
-
|
|
52
|
+
const worker = new Worker(queue, async (job) => this.executor?.(job.name, job.data), {
|
|
45
53
|
connection: this.connection,
|
|
46
54
|
concurrency: options.concurrency ?? 1,
|
|
55
|
+
});
|
|
56
|
+
// Without these listeners an emitted 'error' crashes the process (Node
|
|
57
|
+
// EventEmitter semantics) and exhausted jobs fail invisibly (Q-2).
|
|
58
|
+
worker.on('error', (error) => this.onError(error, { queue, source: 'worker' }));
|
|
59
|
+
worker.on('failed', (job, error) => this.onJobFailed({
|
|
60
|
+
queue,
|
|
61
|
+
job: job?.name ?? '(unknown)',
|
|
62
|
+
...(job?.id !== undefined ? { jobId: String(job.id) } : {}),
|
|
63
|
+
error,
|
|
47
64
|
}));
|
|
65
|
+
this.workers.push(worker);
|
|
48
66
|
}
|
|
49
67
|
async stats(queue) {
|
|
50
68
|
const c = await this.queue(queue).getJobCounts('waiting', 'active', 'completed', 'failed', 'delayed');
|
|
@@ -74,6 +92,7 @@ export class BullmqQueueDriver {
|
|
|
74
92
|
let queue = this.queues.get(name);
|
|
75
93
|
if (!queue) {
|
|
76
94
|
queue = new Queue(name, { connection: this.connection });
|
|
95
|
+
queue.on('error', (error) => this.onError(error, { queue: name, source: 'queue' }));
|
|
77
96
|
this.queues.set(name, queue);
|
|
78
97
|
}
|
|
79
98
|
return queue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basaltkit/queue",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Basalt queues on top of BullMQ: declarative jobs with Zod payloads, context propagation (tenant/requestId) to workers and a sync driver for tests.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"bullmq": "^6.2.1",
|
|
18
|
-
"@basaltkit/core": "^1.
|
|
18
|
+
"@basaltkit/core": "^1.3.0",
|
|
19
19
|
"@basaltkit/events": "^1.0.1"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|