@opens/bullmq 1.0.12 → 2.0.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/README.md +16 -3
- package/dist/index.d.ts +12 -2
- package/dist/index.js +71 -42
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,10 +6,23 @@ BullMQWrapper is a wrapper around BullMQ that simplifies creating and managing t
|
|
|
6
6
|
|
|
7
7
|
### Install
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
After installing the package, you must first start the library before creating any tasks, as shown in the following example
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
```ts
|
|
12
|
+
|
|
13
|
+
import { bullmq } from '@opens/bullmq';
|
|
14
|
+
// if the BULLMQ_REDIS_HOST and BULLMQ_REDIS_PORT environment variables are set this will work out of the box.
|
|
15
|
+
bullmq.start()
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
You may also use a custom connection or redis settings. Either way it works.
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
|
|
22
|
+
import { bullmq } from '@opens/bullmq';
|
|
23
|
+
|
|
24
|
+
bullmq.start({redis: {host:"localhost", port: 6459}})
|
|
25
|
+
```
|
|
13
26
|
|
|
14
27
|
### Creating a Task Queue
|
|
15
28
|
|
package/dist/index.d.ts
CHANGED
|
@@ -3,9 +3,17 @@ import { Redis } from 'ioredis';
|
|
|
3
3
|
import { observer } from '@opens/observability';
|
|
4
4
|
|
|
5
5
|
declare class BullMQWrapper {
|
|
6
|
-
private defaultConnection;
|
|
7
6
|
private taskQueues;
|
|
8
|
-
|
|
7
|
+
private taskWorkers;
|
|
8
|
+
private defaultConnection?;
|
|
9
|
+
start(params?: {
|
|
10
|
+
connection?: Redis;
|
|
11
|
+
} | {
|
|
12
|
+
redis: {
|
|
13
|
+
host?: string;
|
|
14
|
+
port?: number;
|
|
15
|
+
};
|
|
16
|
+
}): void;
|
|
9
17
|
createTask(params: {
|
|
10
18
|
taskName: string;
|
|
11
19
|
defaultOptions: BullMQ.DefaultJobOptions;
|
|
@@ -51,6 +59,8 @@ declare class BullMQWrapper {
|
|
|
51
59
|
taskName: string;
|
|
52
60
|
deduplicationId: string;
|
|
53
61
|
}): Promise<number>;
|
|
62
|
+
shutdown(): Promise<void>;
|
|
63
|
+
getConnection(): Redis | undefined;
|
|
54
64
|
}
|
|
55
65
|
|
|
56
66
|
declare const bullmq: BullMQWrapper;
|
package/dist/index.js
CHANGED
|
@@ -37,12 +37,66 @@ module.exports = __toCommonJS(index_exports);
|
|
|
37
37
|
// src/wrapper.ts
|
|
38
38
|
var BullMQ = __toESM(require("bullmq"));
|
|
39
39
|
var import_observability = require("@opens/observability");
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
|
|
41
|
+
// src/default-connection.ts
|
|
42
|
+
var import_ioredis = require("ioredis");
|
|
43
|
+
var DefaultConnection = class {
|
|
44
|
+
static getInstance(params = {}) {
|
|
45
|
+
const host = params.host ?? process.env.BULLMQ_REDIS_HOST;
|
|
46
|
+
const port = params.port ?? parseInt(process.env.BULLMQ_REDIS_PORT ?? "6379", 10);
|
|
47
|
+
const redis = new import_ioredis.Redis({
|
|
48
|
+
host,
|
|
49
|
+
port,
|
|
50
|
+
maxRetriesPerRequest: null,
|
|
51
|
+
retryStrategy(times) {
|
|
52
|
+
const value = Math.max(Math.min(Math.exp(times), 2e4), 1e3);
|
|
53
|
+
console.log(`[redis]: retry stretegy callback value: ${value}`);
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
redis.on("close", () => {
|
|
58
|
+
console.log("[redis]: closed");
|
|
59
|
+
});
|
|
60
|
+
redis.on("reconnecting", () => {
|
|
61
|
+
console.log("[redis]: reconnecting");
|
|
62
|
+
});
|
|
63
|
+
redis.on("connect", () => {
|
|
64
|
+
console.log("[redis]: connected");
|
|
65
|
+
});
|
|
66
|
+
redis.on("error", (err) => {
|
|
67
|
+
console.log("[redis]: error", err);
|
|
68
|
+
});
|
|
69
|
+
redis.on("connecting", () => {
|
|
70
|
+
console.log("[redis]: connecting");
|
|
71
|
+
});
|
|
72
|
+
redis.on("ready", () => {
|
|
73
|
+
console.log("[redis]: ready");
|
|
74
|
+
});
|
|
75
|
+
return redis;
|
|
43
76
|
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// src/wrapper.ts
|
|
80
|
+
var BullMQWrapper = class {
|
|
44
81
|
taskQueues = /* @__PURE__ */ new Map();
|
|
82
|
+
taskWorkers = /* @__PURE__ */ new Map();
|
|
83
|
+
defaultConnection;
|
|
84
|
+
start(params = {}) {
|
|
85
|
+
if (this.defaultConnection) {
|
|
86
|
+
this.defaultConnection?.disconnect();
|
|
87
|
+
}
|
|
88
|
+
if ("connection" in params && params.connection) {
|
|
89
|
+
this.defaultConnection = params.connection;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if ("redis" in params) {
|
|
93
|
+
this.defaultConnection = DefaultConnection.getInstance({ port: params.redis.port, host: params.redis.host });
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
this.defaultConnection = DefaultConnection.getInstance();
|
|
97
|
+
}
|
|
45
98
|
createTask(params) {
|
|
99
|
+
if (!this.defaultConnection) throw new Error("Default connection is not set. Please call start() method first.");
|
|
46
100
|
const { taskName, up, down, defaultOptions, connection, concurrency } = params;
|
|
47
101
|
if (this.taskQueues.has(taskName)) return;
|
|
48
102
|
const queue = new BullMQ.Queue(taskName, {
|
|
@@ -61,6 +115,7 @@ var BullMQWrapper = class {
|
|
|
61
115
|
return { queue, worker };
|
|
62
116
|
}
|
|
63
117
|
createWorker(params) {
|
|
118
|
+
if (!this.defaultConnection) throw new Error("Default connection is not set. Please call start() method first.");
|
|
64
119
|
const {
|
|
65
120
|
taskName,
|
|
66
121
|
up,
|
|
@@ -109,6 +164,7 @@ var BullMQWrapper = class {
|
|
|
109
164
|
worker.on("closed", () => {
|
|
110
165
|
console.log("[opens/bullmq]: worker closed");
|
|
111
166
|
});
|
|
167
|
+
this.taskWorkers.set(taskName, worker);
|
|
112
168
|
return { worker };
|
|
113
169
|
}
|
|
114
170
|
async publishTask(params) {
|
|
@@ -127,50 +183,23 @@ var BullMQWrapper = class {
|
|
|
127
183
|
const result = await queue.removeDeduplicationKey(params.deduplicationId);
|
|
128
184
|
return result;
|
|
129
185
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
static getInstance() {
|
|
136
|
-
const host = process.env.BULLMQ_REDIS_HOST;
|
|
137
|
-
const port = process.env.BULLMQ_REDIS_PORT;
|
|
138
|
-
if (!host) throw new Error("Environment variable ${BULLMQ_REDIS_HOST} is undefined");
|
|
139
|
-
if (!port) throw new Error("Environment variable ${BULLMQ_REDIS_PORT} is undefined");
|
|
140
|
-
const redis = new import_ioredis.Redis({
|
|
141
|
-
host,
|
|
142
|
-
port: parseInt(port),
|
|
143
|
-
maxRetriesPerRequest: null,
|
|
144
|
-
retryStrategy(times) {
|
|
145
|
-
const value = Math.max(Math.min(Math.exp(times), 2e4), 1e3);
|
|
146
|
-
console.log(`[redis]: retry stretegy callback value: ${value}`);
|
|
147
|
-
return value;
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
redis.on("close", () => {
|
|
151
|
-
console.log("[redis]: closed");
|
|
186
|
+
async shutdown() {
|
|
187
|
+
if (!this.defaultConnection) throw new Error("Default connection is not set. Please call start() method first.");
|
|
188
|
+
const promises = [];
|
|
189
|
+
this.taskWorkers.forEach((worker) => {
|
|
190
|
+
promises.push(worker.close());
|
|
152
191
|
});
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
redis.on("error", (err) => {
|
|
160
|
-
console.log("[redis]: error", err);
|
|
161
|
-
});
|
|
162
|
-
redis.on("connecting", () => {
|
|
163
|
-
console.log("[redis]: connecting");
|
|
164
|
-
});
|
|
165
|
-
redis.on("ready", () => {
|
|
166
|
-
console.log("[redis]: ready");
|
|
167
|
-
});
|
|
168
|
-
return redis;
|
|
192
|
+
promises.push(this.defaultConnection.quit());
|
|
193
|
+
await Promise.all(promises);
|
|
194
|
+
console.log(`[@opens/bullmq]: all workers closed`);
|
|
195
|
+
}
|
|
196
|
+
getConnection() {
|
|
197
|
+
return this.defaultConnection;
|
|
169
198
|
}
|
|
170
199
|
};
|
|
171
200
|
|
|
172
201
|
// src/index.ts
|
|
173
|
-
var bullmq = new BullMQWrapper(
|
|
202
|
+
var bullmq = new BullMQWrapper();
|
|
174
203
|
// Annotate the CommonJS export names for ESM import in node:
|
|
175
204
|
0 && (module.exports = {
|
|
176
205
|
bullmq
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/wrapper.ts","../src/default-connection.ts"],"sourcesContent":["import { BullMQWrapper } from './wrapper';\nimport { DefaultConnection } from './default-connection';\nexport const bullmq = new BullMQWrapper(DefaultConnection.getInstance());\n","import * as BullMQ from 'bullmq';\nimport { Redis } from 'ioredis';\nimport { observer, TRACE_TYPE } from '@opens/observability';\nexport class BullMQWrapper {\n private taskQueues: Map<string, BullMQ.Queue> = new Map();\n\n constructor(private defaultConnection: Redis) {}\n\n public createTask(params: {\n taskName: string;\n defaultOptions: BullMQ.DefaultJobOptions;\n connection?: Redis;\n up?: (data: any, job: BullMQ.Job) => Promise<void>;\n down?: (data: any, job: BullMQ.Job, err: unknown) => Promise<void>;\n concurrency?: number;\n removeOnCompleteAge?: number;\n removeOnCompleteCount?: number;\n removeOnFailAge?: number;\n removeOnFailCount?: number;\n tracer?: typeof observer.tracer;\n }) {\n const { taskName, up, down, defaultOptions, connection, concurrency } = params;\n if (this.taskQueues.has(taskName)) return;\n\n const queue = new BullMQ.Queue(taskName, {\n connection: this.defaultConnection ?? connection,\n defaultJobOptions: { backoff: { delay: 1000 * 60 * 5, type: 'fixed' }, attempts: 10, ...defaultOptions },\n });\n this.taskQueues.set(taskName, queue);\n console.debug(`[@opens/bullmq]: task queue'${taskName}' created`);\n if (!up) return { queue };\n\n const { worker } = this.createWorker({\n up,\n down,\n concurrency: concurrency ?? 1,\n ...params,\n });\n return { queue, worker };\n }\n\n public createWorker(params: {\n taskName: string;\n up: (data: any, job: BullMQ.Job) => Promise<void>;\n down?: (data: any, job: BullMQ.Job, err: unknown) => Promise<void>;\n connection?: Redis;\n concurrency: number;\n tracer?: typeof observer.tracer;\n removeOnCompleteAge?: number;\n removeOnCompleteCount?: number;\n removeOnFailAge?: number;\n removeOnFailCount?: number;\n onError?: Function;\n }) {\n const {\n taskName,\n up,\n down,\n concurrency,\n connection,\n removeOnFailCount,\n removeOnCompleteAge,\n removeOnCompleteCount,\n removeOnFailAge,\n tracer,\n } = params;\n\n const registeredQueue = this.taskQueues.get(taskName);\n if (!registeredQueue) throw new Error(`No task queue for [${taskName}] found`);\n const fn = async (job: BullMQ.Job) => {\n try {\n await up(job.data, job);\n } catch (error) {\n if (down) await down(job.data, job, error);\n throw error;\n } finally {\n }\n };\n const handler = tracer?.instrumentFunc({ name: taskName, type: TRACE_TYPE.TASK }, fn) ?? fn;\n\n const worker = new BullMQ.Worker(taskName, handler, {\n concurrency,\n connection: connection ?? this.defaultConnection,\n removeOnComplete: {\n age: removeOnCompleteAge ?? 60 * 60,\n count: removeOnCompleteCount ?? 20,\n },\n removeOnFail: {\n age: removeOnFailAge ?? 60 * 60,\n count: removeOnFailCount ?? 50,\n },\n });\n worker.on('ready', () => {\n console.log(`[opens/bullmq]: '${taskName}' worker is ready`);\n });\n worker.on('error', (err) => {\n console.error('[opens/bullmq]: error', err);\n });\n worker.on('ioredis:close', () => {\n console.log('[opens/bullmq]: redis has closed');\n });\n worker.on('closed', () => {\n console.log('[opens/bullmq]: worker closed');\n });\n return { worker };\n }\n\n public async publishTask(params: {\n taskData: any;\n taskId?: string;\n taskName: string;\n taskOptions?: BullMQ.JobsOptions;\n }) {\n const queue = this.taskQueues.get(params.taskName);\n if (!queue) return null;\n const jobName = params.taskId ? `${params.taskName}_${params.taskId}` : '';\n const job = await queue.add(jobName, params.taskData, params.taskOptions);\n return job.asJSON();\n }\n\n public getTaskCount() {\n return this.taskQueues.size;\n }\n\n public async removeDeduplication(params: { taskName: string; deduplicationId: string }) {\n const queue = this.taskQueues.get(params.taskName);\n if (!queue) return 0;\n const result = await queue.removeDeduplicationKey(params.deduplicationId);\n return result;\n }\n}\n","import { Redis } from 'ioredis';\nexport class DefaultConnection {\n static getInstance() {\n const host = process.env.BULLMQ_REDIS_HOST;\n const port = process.env.BULLMQ_REDIS_PORT;\n if (!host) throw new Error('Environment variable ${BULLMQ_REDIS_HOST} is undefined');\n if (!port) throw new Error('Environment variable ${BULLMQ_REDIS_PORT} is undefined');\n const redis = new Redis({\n host,\n port: parseInt(port),\n maxRetriesPerRequest: null,\n retryStrategy(times: number) {\n const value = Math.max(Math.min(Math.exp(times), 20000), 1000);\n console.log(`[redis]: retry stretegy callback value: ${value}`);\n return value;\n },\n });\n redis.on('close', () => {\n console.log('[redis]: closed');\n });\n redis.on('reconnecting', () => {\n console.log('[redis]: reconnecting');\n });\n redis.on('connect', () => {\n console.log('[redis]: connected');\n });\n redis.on('error', (err) => {\n console.log('[redis]: error', err);\n });\n redis.on('connecting', () => {\n console.log('[redis]: connecting');\n });\n redis.on('ready', () => {\n console.log('[redis]: ready');\n });\n return redis;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/wrapper.ts","../src/default-connection.ts"],"sourcesContent":["import { BullMQWrapper } from './wrapper';\nexport const bullmq = new BullMQWrapper();\n","import * as BullMQ from 'bullmq';\nimport { Redis } from 'ioredis';\nimport { observer, TRACE_TYPE } from '@opens/observability';\nimport { DefaultConnection } from './default-connection';\nexport class BullMQWrapper {\n private taskQueues: Map<string, BullMQ.Queue> = new Map();\n private taskWorkers: Map<string, BullMQ.Worker> = new Map();\n private defaultConnection?: Redis;\n\n start(params: { connection?: Redis } | { redis: { host?: string; port?: number } } = {}) {\n if (this.defaultConnection) {\n this.defaultConnection?.disconnect();\n }\n\n if ('connection' in params && params.connection) {\n this.defaultConnection = params.connection;\n return;\n }\n\n if ('redis' in params) {\n this.defaultConnection = DefaultConnection.getInstance({ port: params.redis.port, host: params.redis.host });\n return;\n }\n\n this.defaultConnection = DefaultConnection.getInstance();\n }\n\n public createTask(params: {\n taskName: string;\n defaultOptions: BullMQ.DefaultJobOptions;\n connection?: Redis;\n up?: (data: any, job: BullMQ.Job) => Promise<void>;\n down?: (data: any, job: BullMQ.Job, err: unknown) => Promise<void>;\n concurrency?: number;\n removeOnCompleteAge?: number;\n removeOnCompleteCount?: number;\n removeOnFailAge?: number;\n removeOnFailCount?: number;\n tracer?: typeof observer.tracer;\n }) {\n if (!this.defaultConnection) throw new Error('Default connection is not set. Please call start() method first.');\n\n const { taskName, up, down, defaultOptions, connection, concurrency } = params;\n if (this.taskQueues.has(taskName)) return;\n\n const queue = new BullMQ.Queue(taskName, {\n connection: this.defaultConnection ?? connection,\n defaultJobOptions: { backoff: { delay: 1000 * 60 * 5, type: 'fixed' }, attempts: 10, ...defaultOptions },\n });\n this.taskQueues.set(taskName, queue);\n console.debug(`[@opens/bullmq]: task queue'${taskName}' created`);\n if (!up) return { queue };\n\n const { worker } = this.createWorker({\n up,\n down,\n concurrency: concurrency ?? 1,\n ...params,\n });\n return { queue, worker };\n }\n\n public createWorker(params: {\n taskName: string;\n up: (data: any, job: BullMQ.Job) => Promise<void>;\n down?: (data: any, job: BullMQ.Job, err: unknown) => Promise<void>;\n connection?: Redis;\n concurrency: number;\n tracer?: typeof observer.tracer;\n removeOnCompleteAge?: number;\n removeOnCompleteCount?: number;\n removeOnFailAge?: number;\n removeOnFailCount?: number;\n onError?: Function;\n }) {\n if (!this.defaultConnection) throw new Error('Default connection is not set. Please call start() method first.');\n const {\n taskName,\n up,\n down,\n concurrency,\n connection,\n removeOnFailCount,\n removeOnCompleteAge,\n removeOnCompleteCount,\n removeOnFailAge,\n tracer,\n } = params;\n\n const registeredQueue = this.taskQueues.get(taskName);\n if (!registeredQueue) throw new Error(`No task queue for [${taskName}] found`);\n const fn = async (job: BullMQ.Job) => {\n try {\n await up(job.data, job);\n } catch (error) {\n if (down) await down(job.data, job, error);\n throw error;\n } finally {\n }\n };\n const handler = tracer?.instrumentFunc({ name: taskName, type: TRACE_TYPE.TASK }, fn) ?? fn;\n\n const worker = new BullMQ.Worker(taskName, handler, {\n concurrency,\n connection: connection ?? this.defaultConnection,\n removeOnComplete: {\n age: removeOnCompleteAge ?? 60 * 60,\n count: removeOnCompleteCount ?? 20,\n },\n removeOnFail: {\n age: removeOnFailAge ?? 60 * 60,\n count: removeOnFailCount ?? 50,\n },\n });\n worker.on('ready', () => {\n console.log(`[opens/bullmq]: '${taskName}' worker is ready`);\n });\n worker.on('error', (err) => {\n console.error('[opens/bullmq]: error', err);\n });\n worker.on('ioredis:close', () => {\n console.log('[opens/bullmq]: redis has closed');\n });\n worker.on('closed', () => {\n console.log('[opens/bullmq]: worker closed');\n });\n this.taskWorkers.set(taskName, worker);\n return { worker };\n }\n\n public async publishTask(params: {\n taskData: any;\n taskId?: string;\n taskName: string;\n taskOptions?: BullMQ.JobsOptions;\n }) {\n const queue = this.taskQueues.get(params.taskName);\n if (!queue) return null;\n const jobName = params.taskId ? `${params.taskName}_${params.taskId}` : '';\n const job = await queue.add(jobName, params.taskData, params.taskOptions);\n return job.asJSON();\n }\n\n public getTaskCount() {\n return this.taskQueues.size;\n }\n\n public async removeDeduplication(params: { taskName: string; deduplicationId: string }) {\n const queue = this.taskQueues.get(params.taskName);\n if (!queue) return 0;\n const result = await queue.removeDeduplicationKey(params.deduplicationId);\n return result;\n }\n\n public async shutdown() {\n if (!this.defaultConnection) throw new Error('Default connection is not set. Please call start() method first.');\n const promises: Promise<any>[] = [];\n this.taskWorkers.forEach((worker) => {\n promises.push(worker.close());\n });\n promises.push(this.defaultConnection.quit());\n await Promise.all(promises);\n console.log(`[@opens/bullmq]: all workers closed`);\n }\n\n public getConnection() {\n return this.defaultConnection;\n }\n}\n","import { Redis } from 'ioredis';\nexport class DefaultConnection {\n static getInstance(params: { host?: string; port?: number } = {}): Redis {\n const host = params.host ?? process.env.BULLMQ_REDIS_HOST;\n const port = params.port ?? parseInt(process.env.BULLMQ_REDIS_PORT ?? '6379', 10);\n const redis = new Redis({\n host,\n port,\n maxRetriesPerRequest: null,\n retryStrategy(times: number) {\n const value = Math.max(Math.min(Math.exp(times), 20000), 1000);\n console.log(`[redis]: retry stretegy callback value: ${value}`);\n return value;\n },\n });\n redis.on('close', () => {\n console.log('[redis]: closed');\n });\n redis.on('reconnecting', () => {\n console.log('[redis]: reconnecting');\n });\n redis.on('connect', () => {\n console.log('[redis]: connected');\n });\n redis.on('error', (err) => {\n console.log('[redis]: error', err);\n });\n redis.on('connecting', () => {\n console.log('[redis]: connecting');\n });\n redis.on('ready', () => {\n console.log('[redis]: ready');\n });\n return redis;\n }\n}\n"],"mappings":"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","names":[]}
|