@opens/bullmq 3.1.2 → 3.1.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/dist/index.d.ts +16 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -2,11 +2,18 @@ import * as BullMQ from 'bullmq';
|
|
|
2
2
|
import { Redis } from 'ioredis';
|
|
3
3
|
import { observer } from '@opens/observability';
|
|
4
4
|
|
|
5
|
+
type FlowNode = {
|
|
6
|
+
taskName: string;
|
|
7
|
+
taskData: any;
|
|
8
|
+
taskOptions?: BullMQ.JobsOptions;
|
|
9
|
+
children?: FlowNode[];
|
|
10
|
+
};
|
|
5
11
|
declare class BullMQWrapper {
|
|
6
12
|
private taskQueues;
|
|
7
13
|
private taskWorkers;
|
|
8
14
|
private defaultConnection?;
|
|
9
15
|
private observer?;
|
|
16
|
+
private flowProducer?;
|
|
10
17
|
start(params?: {
|
|
11
18
|
connection?: Redis;
|
|
12
19
|
oberserver?: typeof observer;
|
|
@@ -51,6 +58,15 @@ declare class BullMQWrapper {
|
|
|
51
58
|
}): {
|
|
52
59
|
worker: BullMQ.Worker<any, void, string>;
|
|
53
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* Builds a FlowProducer job node from a flow node, including its children.
|
|
63
|
+
*/
|
|
64
|
+
createFlowNode(node: FlowNode): BullMQ.FlowJob;
|
|
65
|
+
private collectFlowTaskNames;
|
|
66
|
+
publishFlow(params: {
|
|
67
|
+
parent: FlowNode;
|
|
68
|
+
children: FlowNode[];
|
|
69
|
+
}): Promise<BullMQ.JobNode>;
|
|
54
70
|
publishTask(params: {
|
|
55
71
|
taskData: any;
|
|
56
72
|
taskId?: string;
|
package/dist/index.js
CHANGED
|
@@ -82,6 +82,7 @@ var BullMQWrapper = class {
|
|
|
82
82
|
taskWorkers = /* @__PURE__ */ new Map();
|
|
83
83
|
defaultConnection;
|
|
84
84
|
observer;
|
|
85
|
+
flowProducer;
|
|
85
86
|
start(params = {}) {
|
|
86
87
|
if (this.defaultConnection) {
|
|
87
88
|
this.defaultConnection?.disconnect();
|
|
@@ -170,6 +171,33 @@ var BullMQWrapper = class {
|
|
|
170
171
|
this.taskWorkers.set(taskName, worker);
|
|
171
172
|
return { worker };
|
|
172
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Builds a FlowProducer job node from a flow node, including its children.
|
|
176
|
+
*/
|
|
177
|
+
createFlowNode(node) {
|
|
178
|
+
return {
|
|
179
|
+
name: node.taskName,
|
|
180
|
+
queueName: node.taskName,
|
|
181
|
+
data: node.taskData,
|
|
182
|
+
opts: node.taskOptions,
|
|
183
|
+
children: node.children?.map((child) => this.createFlowNode(child))
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
collectFlowTaskNames(nodes) {
|
|
187
|
+
return nodes.flatMap((node) => [node.taskName, ...this.collectFlowTaskNames(node.children ?? [])]);
|
|
188
|
+
}
|
|
189
|
+
async publishFlow(params) {
|
|
190
|
+
if (!this.defaultConnection) throw new Error("Default connection is not set. Please call start() method first.");
|
|
191
|
+
if (!this.flowProducer) this.flowProducer = new BullMQ.FlowProducer({ connection: this.defaultConnection });
|
|
192
|
+
const involvedTaskNames = [params.parent.taskName, ...this.collectFlowTaskNames(params.children)];
|
|
193
|
+
const queuesOptions = {};
|
|
194
|
+
for (const taskName of involvedTaskNames) {
|
|
195
|
+
const defaultJobOptions = this.taskQueues.get(taskName)?.opts.defaultJobOptions;
|
|
196
|
+
if (defaultJobOptions) queuesOptions[taskName] = { defaultJobOptions };
|
|
197
|
+
}
|
|
198
|
+
const flowJob = this.createFlowNode({ ...params.parent, children: params.children });
|
|
199
|
+
return this.flowProducer.add(flowJob, { queuesOptions });
|
|
200
|
+
}
|
|
173
201
|
async publishTask(params) {
|
|
174
202
|
const queue = this.taskQueues.get(params.taskName);
|
|
175
203
|
if (!queue) return null;
|
|
@@ -192,6 +220,7 @@ var BullMQWrapper = class {
|
|
|
192
220
|
this.taskWorkers.forEach((worker) => {
|
|
193
221
|
promises.push(worker.close());
|
|
194
222
|
});
|
|
223
|
+
if (this.flowProducer) promises.push(this.flowProducer.close());
|
|
195
224
|
promises.push(this.defaultConnection.quit());
|
|
196
225
|
await Promise.all(promises);
|
|
197
226
|
console.log(`[@opens/bullmq]: all workers closed`);
|
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';\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 private observer?: typeof observer;\n\n start(\n params:\n | { connection?: Redis; oberserver?: typeof observer }\n | { redis: { host?: string; port?: number; oberserver?: typeof observer } } = {},\n ) {\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 this.observer = params.oberserver;\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 trace = tracer ?? this.observer?.tracer;\n const handler = trace?.instrumentAsyncFunc({ 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":[]}
|
|
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';\n\ntype FlowNode = {\n taskName: string;\n taskData: any;\n taskOptions?: BullMQ.JobsOptions;\n children?: FlowNode[];\n};\n\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 private observer?: typeof observer;\n private flowProducer?: BullMQ.FlowProducer;\n\n start(\n params:\n | { connection?: Redis; oberserver?: typeof observer }\n | { redis: { host?: string; port?: number; oberserver?: typeof observer } } = {},\n ) {\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 this.observer = params.oberserver;\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 trace = tracer ?? this.observer?.tracer;\n const handler = trace?.instrumentAsyncFunc({ 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 /**\n * Builds a FlowProducer job node from a flow node, including its children.\n */\n public createFlowNode(node: FlowNode): BullMQ.FlowJob {\n return {\n name: node.taskName,\n queueName: node.taskName,\n data: node.taskData,\n opts: node.taskOptions,\n children: node.children?.map((child) => this.createFlowNode(child)),\n };\n }\n\n private collectFlowTaskNames(nodes: FlowNode[]): string[] {\n return nodes.flatMap((node) => [node.taskName, ...this.collectFlowTaskNames(node.children ?? [])]);\n }\n\n public async publishFlow(params: { parent: FlowNode; children: FlowNode[] }) {\n if (!this.defaultConnection) throw new Error('Default connection is not set. Please call start() method first.');\n\n if (!this.flowProducer) this.flowProducer = new BullMQ.FlowProducer({ connection: this.defaultConnection });\n\n const involvedTaskNames = [params.parent.taskName, ...this.collectFlowTaskNames(params.children)];\n const queuesOptions: BullMQ.FlowQueuesOpts = {};\n for (const taskName of involvedTaskNames) {\n const defaultJobOptions = this.taskQueues.get(taskName)?.opts.defaultJobOptions;\n if (defaultJobOptions) queuesOptions[taskName] = { defaultJobOptions };\n }\n\n const flowJob = this.createFlowNode({ ...params.parent, children: params.children });\n return this.flowProducer.add(flowJob, { queuesOptions });\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 if (this.flowProducer) promises.push(this.flowProducer.close());\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":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opens/bullmq",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.3",
|
|
4
4
|
"description": "A wrapper around bullmq",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"author": "Joao Victor Clementino",
|
|
25
25
|
"license": "ISC",
|
|
26
26
|
"devDependencies": {
|
|
27
|
+
"@opens/observability": "^1.1.1",
|
|
27
28
|
"ioredis-mock": "^8.9.0",
|
|
28
29
|
"tsup": "^8.3.5",
|
|
29
30
|
"typescript": "^5.7.3",
|
|
@@ -45,4 +46,4 @@
|
|
|
45
46
|
"optional": true
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
|
-
}
|
|
49
|
+
}
|