@pikku/queue-bullmq 0.11.2 → 0.12.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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 0.12.0
2
+
3
+ ### New Features
4
+
5
+ - Recurring cron scheduled tasks support via `BullSchedulerService`
6
+ - `setServices()`, `start()`, `stop()` lifecycle methods on scheduler and queue workers
7
+
1
8
  ## 0.11.0
2
9
 
3
10
  ## 0.11.2
@@ -8,8 +15,6 @@
8
15
  - Updated dependencies [db9c7bf]
9
16
  - @pikku/core@0.11.2
10
17
 
11
- ## 0.11.2
12
-
13
18
  ### Fixes
14
19
 
15
20
  - ddd87eaf: Simplify CreateWireServices type signature for custom Config compatibility
@@ -1,6 +1,6 @@
1
1
  import { ConnectionOptions, WorkerOptions } from 'bullmq';
2
- import type { QueueWorkers, PikkuWorkerConfig, QueueConfigMapping, ConfigValidationResult } from '@pikku/core/queue';
3
- import type { CoreSingletonServices, CreateWireServices } from '@pikku/core';
2
+ import type { QueueWorkers, PikkuWorkerConfig, QueueConfigMapping, ConfigValidationResult, QueueJob } from '@pikku/core/queue';
3
+ import type { Logger } from '@pikku/core/services';
4
4
  export declare const mapPikkuWorkerToBull: (workerConfig?: PikkuWorkerConfig) => Omit<WorkerOptions, "connection">;
5
5
  /**
6
6
  * Bull/Redis queue service implementation
@@ -8,8 +8,6 @@ export declare const mapPikkuWorkerToBull: (workerConfig?: PikkuWorkerConfig) =>
8
8
  */
9
9
  export declare class BullQueueWorkers implements QueueWorkers {
10
10
  private redisConnectionOptions;
11
- private singletonServices;
12
- private createWireServices?;
13
11
  readonly name = "bull";
14
12
  readonly supportsResults = true;
15
13
  /**
@@ -19,7 +17,13 @@ export declare class BullQueueWorkers implements QueueWorkers {
19
17
  readonly configMappings: QueueConfigMapping;
20
18
  private workers;
21
19
  private queueEvents;
22
- constructor(redisConnectionOptions: ConnectionOptions, singletonServices: CoreSingletonServices, createWireServices?: CreateWireServices | undefined);
20
+ private runJob?;
21
+ private logger?;
22
+ constructor(redisConnectionOptions: ConnectionOptions);
23
+ setJobRunner(runJob: (params: {
24
+ job: QueueJob;
25
+ updateProgress?: (progress: number | string | object) => Promise<void>;
26
+ }) => Promise<void>, logger: Logger): void;
23
27
  /**
24
28
  * Scan state and register all compatible processors
25
29
  */
@@ -1,5 +1,5 @@
1
1
  import { Worker, } from 'bullmq';
2
- import { runQueueJob, registerQueueWorkers, QueueJobFailedError, QueueJobDiscardedError, } from '@pikku/core/queue';
2
+ import { registerQueueWorkers, QueueJobFailedError, QueueJobDiscardedError, } from '@pikku/core/queue';
3
3
  import { mapBullJobToQueueJob } from './utils.js';
4
4
  export const mapPikkuWorkerToBull = (workerConfig) => {
5
5
  const workerOptions = {};
@@ -37,8 +37,6 @@ export const mapPikkuWorkerToBull = (workerConfig) => {
37
37
  */
38
38
  export class BullQueueWorkers {
39
39
  redisConnectionOptions;
40
- singletonServices;
41
- createWireServices;
42
40
  name = 'bull';
43
41
  supportsResults = true;
44
42
  /**
@@ -101,21 +99,26 @@ export class BullQueueWorkers {
101
99
  };
102
100
  workers = new Map();
103
101
  queueEvents = new Map();
104
- constructor(redisConnectionOptions, singletonServices, createWireServices) {
102
+ runJob;
103
+ logger;
104
+ constructor(redisConnectionOptions) {
105
105
  this.redisConnectionOptions = redisConnectionOptions;
106
- this.singletonServices = singletonServices;
107
- this.createWireServices = createWireServices;
106
+ }
107
+ setJobRunner(runJob, logger) {
108
+ this.runJob = runJob;
109
+ this.logger = logger;
108
110
  }
109
111
  /**
110
112
  * Scan state and register all compatible processors
111
113
  */
112
114
  async registerQueues() {
113
- return await registerQueueWorkers(this.configMappings, this.singletonServices.logger, async (queueName, processor) => {
114
- const worker = new Worker(processor.queueName, async (job) => {
115
+ if (!this.runJob || !this.logger) {
116
+ throw new Error('BullQueueWorkers requires setJobRunner() before registerQueues()');
117
+ }
118
+ return await registerQueueWorkers(this.configMappings, this.logger, async (queueName, processor) => {
119
+ const worker = new Worker(processor.name, async (job) => {
115
120
  try {
116
- return await runQueueJob({
117
- singletonServices: this.singletonServices,
118
- createWireServices: this.createWireServices,
121
+ return await this.runJob({
119
122
  job: await mapBullJobToQueueJob(job, this.redisConnectionOptions, this.queueEvents),
120
123
  updateProgress: async (progress) => {
121
124
  await job.updateProgress(progress);
@@ -1,12 +1,19 @@
1
1
  import { ConnectionOptions } from 'bullmq';
2
- import { SchedulerService, ScheduledTaskInfo, ScheduledTaskSummary, CoreUserSession } from '@pikku/core';
3
- /**
4
- * BullMQ scheduler service implementation
5
- * Uses BullMQ's delayed jobs for one-time execution
6
- */
2
+ import { SchedulerService, SchedulerRuntimeHandlers, ScheduledTaskInfo, ScheduledTaskSummary, CoreUserSession } from '@pikku/core';
7
3
  export declare class BullSchedulerService extends SchedulerService {
4
+ private redisConnectionOptions;
8
5
  private queue;
6
+ private recurringQueue;
7
+ private recurringWorker?;
8
+ private repeatJobKeys;
9
+ private handlers?;
9
10
  constructor(redisConnectionOptions: ConnectionOptions);
11
+ /**
12
+ * Set services needed for processing recurring tasks.
13
+ * Must be called before start() since the scheduler is typically
14
+ * created before singletonServices are available.
15
+ */
16
+ setServices(handlers: SchedulerRuntimeHandlers): void;
10
17
  /**
11
18
  * Initialize - wait for queue to be ready
12
19
  */
@@ -32,4 +39,13 @@ export declare class BullSchedulerService extends SchedulerService {
32
39
  * Close the queue connection
33
40
  */
34
41
  close(): Promise<void>;
42
+ /**
43
+ * Start recurring scheduled tasks.
44
+ * Creates a BullMQ Worker to process repeat jobs via runScheduledTask.
45
+ */
46
+ start(): Promise<void>;
47
+ /**
48
+ * Stop recurring scheduled tasks by removing repeat jobs.
49
+ */
50
+ stop(): Promise<void>;
35
51
  }
@@ -1,16 +1,31 @@
1
- import { Queue } from 'bullmq';
1
+ import { Queue, Worker } from 'bullmq';
2
2
  import { SchedulerService, parseDurationString, } from '@pikku/core';
3
- /**
4
- * BullMQ scheduler service implementation
5
- * Uses BullMQ's delayed jobs for one-time execution
6
- */
3
+ import { getScheduledTasks } from '@pikku/core/scheduler';
4
+ const RECURRING_QUEUE_NAME = 'pikku-recurring-scheduled-task';
7
5
  export class BullSchedulerService extends SchedulerService {
6
+ redisConnectionOptions;
8
7
  queue;
8
+ recurringQueue;
9
+ recurringWorker;
10
+ repeatJobKeys = [];
11
+ handlers;
9
12
  constructor(redisConnectionOptions) {
10
13
  super();
14
+ this.redisConnectionOptions = redisConnectionOptions;
11
15
  this.queue = new Queue('pikku-remote-internal-rpc', {
12
16
  connection: redisConnectionOptions,
13
17
  });
18
+ this.recurringQueue = new Queue(RECURRING_QUEUE_NAME, {
19
+ connection: redisConnectionOptions,
20
+ });
21
+ }
22
+ /**
23
+ * Set services needed for processing recurring tasks.
24
+ * Must be called before start() since the scheduler is typically
25
+ * created before singletonServices are available.
26
+ */
27
+ setServices(handlers) {
28
+ this.handlers = handlers;
14
29
  }
15
30
  /**
16
31
  * Initialize - wait for queue to be ready
@@ -95,6 +110,51 @@ export class BullSchedulerService extends SchedulerService {
95
110
  * Close the queue connection
96
111
  */
97
112
  async close() {
113
+ if (this.recurringWorker) {
114
+ await this.recurringWorker.close();
115
+ }
116
+ await this.recurringQueue.close();
98
117
  await this.queue.close();
99
118
  }
119
+ /**
120
+ * Start recurring scheduled tasks.
121
+ * Creates a BullMQ Worker to process repeat jobs via runScheduledTask.
122
+ */
123
+ async start() {
124
+ if (!this.handlers) {
125
+ throw new Error('BullSchedulerService requires setServices() before start()');
126
+ }
127
+ const scheduledTasks = getScheduledTasks();
128
+ // Create a worker to process recurring scheduled task jobs
129
+ this.recurringWorker = new Worker(RECURRING_QUEUE_NAME, async (job) => {
130
+ const { rpcName } = job.data;
131
+ this.handlers.logger.info(`Running scheduled task: ${rpcName}`);
132
+ await this.handlers.runScheduledTask(rpcName);
133
+ }, { connection: this.redisConnectionOptions });
134
+ this.recurringWorker.on('error', (err) => {
135
+ this.handlers.logger.error(`Recurring task worker error: ${err}`);
136
+ });
137
+ for (const [name, task] of scheduledTasks) {
138
+ const job = await this.recurringQueue.add(name, { rpcName: name }, {
139
+ repeat: { pattern: task.schedule },
140
+ jobId: `recurring:${name}`,
141
+ });
142
+ if (job.repeatJobKey) {
143
+ this.repeatJobKeys.push(job.repeatJobKey);
144
+ }
145
+ }
146
+ }
147
+ /**
148
+ * Stop recurring scheduled tasks by removing repeat jobs.
149
+ */
150
+ async stop() {
151
+ for (const key of this.repeatJobKeys) {
152
+ await this.recurringQueue.removeRepeatableByKey(key);
153
+ }
154
+ this.repeatJobKeys = [];
155
+ if (this.recurringWorker) {
156
+ await this.recurringWorker.close();
157
+ this.recurringWorker = undefined;
158
+ }
159
+ }
100
160
  }
@@ -29,6 +29,7 @@ export declare class BullServiceFactory {
29
29
  * Get the scheduler service for managing delayed tasks
30
30
  */
31
31
  getSchedulerService(): BullSchedulerService;
32
+ setSchedulerRuntime(singletonServices: CoreSingletonServices, createWireServices?: CreateWireServices): void;
32
33
  /**
33
34
  * Close all services
34
35
  */
@@ -1,6 +1,8 @@
1
1
  import { BullQueueService } from './bull-queue-service.js';
2
2
  import { BullQueueWorkers } from './bull-queue-worker.js';
3
3
  import { BullSchedulerService } from './bull-scheduler-service.js';
4
+ import { createQueueJobRunner } from '@pikku/core/queue';
5
+ import { createSchedulerRuntimeHandlers } from '@pikku/core/scheduler';
4
6
  /**
5
7
  * Factory class for BullMQ services
6
8
  * Manages Redis connection options shared across queue, worker, and scheduler services
@@ -33,8 +35,9 @@ export class BullServiceFactory {
33
35
  */
34
36
  getQueueWorkers(singletonServices, createWireServices) {
35
37
  if (!this.queueWorkers) {
36
- this.queueWorkers = new BullQueueWorkers(this.redisConnectionOptions, singletonServices, createWireServices);
38
+ this.queueWorkers = new BullQueueWorkers(this.redisConnectionOptions);
37
39
  }
40
+ this.queueWorkers.setJobRunner(createQueueJobRunner({ singletonServices, createWireServices }), singletonServices.logger);
38
41
  return this.queueWorkers;
39
42
  }
40
43
  /**
@@ -46,6 +49,12 @@ export class BullServiceFactory {
46
49
  }
47
50
  return this.schedulerService;
48
51
  }
52
+ setSchedulerRuntime(singletonServices, createWireServices) {
53
+ this.getSchedulerService().setServices(createSchedulerRuntimeHandlers({
54
+ singletonServices,
55
+ createWireServices,
56
+ }));
57
+ }
49
58
  /**
50
59
  * Close all services
51
60
  */
package/dist/utils.js CHANGED
@@ -29,10 +29,11 @@ export const mapBullJobToQueueJob = async (bullJob, redisConnection, queueEvents
29
29
  result: bullJob.returnvalue,
30
30
  status: async () => mapBullStateToStatus(await bullJob.getState()),
31
31
  waitForCompletion: async (ttl) => {
32
- let queueEvents = queueEventsMap.get(bullJob.name);
32
+ let queueEvents = queueEventsMap.get(bullJob.queueName);
33
33
  if (!queueEvents) {
34
- queueEvents = new QueueEvents(bullJob.name, redisConnection ? { connection: redisConnection } : undefined);
35
- queueEventsMap.set(bullJob.name, queueEvents);
34
+ queueEvents = new QueueEvents(bullJob.queueName, redisConnection ? { connection: redisConnection } : undefined);
35
+ queueEventsMap.set(bullJob.queueName, queueEvents);
36
+ await queueEvents.waitUntilReady();
36
37
  }
37
38
  return await bullJob.waitUntilFinished(queueEvents, ttl);
38
39
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/queue-bullmq",
3
- "version": "0.11.2",
3
+ "version": "0.12.0",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "MIT",
6
6
  "module": "dist/index.js",
@@ -13,11 +13,11 @@
13
13
  "release": "npm run build && npm test"
14
14
  },
15
15
  "peerDependencies": {
16
- "@pikku/core": "^0.11.2"
16
+ "@pikku/core": "^0.12.0"
17
17
  },
18
18
  "dependencies": {
19
- "bullmq": "^5.63.2",
20
- "ioredis": "^5.8.2"
19
+ "bullmq": "^5.67.3",
20
+ "ioredis": "^5.9.2"
21
21
  },
22
22
  "devDependencies": {
23
23
  "typescript": "^5.9"
@@ -0,0 +1,15 @@
1
+ import { describe, test } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+
4
+ import { BullQueueWorkers } from './bull-queue-worker.js'
5
+
6
+ describe('BullQueueWorkers', () => {
7
+ test('requires setJobRunner before registerQueues', async () => {
8
+ const workers = new BullQueueWorkers({})
9
+
10
+ await assert.rejects(() => workers.registerQueues(), {
11
+ message:
12
+ 'BullQueueWorkers requires setJobRunner() before registerQueues()',
13
+ })
14
+ })
15
+ })
@@ -9,14 +9,14 @@ import type {
9
9
  PikkuWorkerConfig,
10
10
  QueueConfigMapping,
11
11
  ConfigValidationResult,
12
+ QueueJob,
12
13
  } from '@pikku/core/queue'
13
14
  import {
14
- runQueueJob,
15
15
  registerQueueWorkers,
16
16
  QueueJobFailedError,
17
17
  QueueJobDiscardedError,
18
18
  } from '@pikku/core/queue'
19
- import type { CoreSingletonServices, CreateWireServices } from '@pikku/core'
19
+ import type { Logger } from '@pikku/core/services'
20
20
  import { mapBullJobToQueueJob } from './utils.js'
21
21
 
22
22
  export const mapPikkuWorkerToBull = (
@@ -137,28 +137,46 @@ export class BullQueueWorkers implements QueueWorkers {
137
137
 
138
138
  private workers = new Map<string, Bull.Worker>()
139
139
  private queueEvents = new Map<string, QueueEvents>()
140
-
141
- constructor(
142
- private redisConnectionOptions: ConnectionOptions,
143
- private singletonServices: CoreSingletonServices,
144
- private createWireServices?: CreateWireServices
145
- ) {}
140
+ private runJob?:
141
+ | ((params: {
142
+ job: QueueJob
143
+ updateProgress?: (progress: number | string | object) => Promise<void>
144
+ }) => Promise<void>)
145
+ | undefined
146
+ private logger?: Logger
147
+
148
+ constructor(private redisConnectionOptions: ConnectionOptions) {}
149
+
150
+ setJobRunner(
151
+ runJob: (params: {
152
+ job: QueueJob
153
+ updateProgress?: (progress: number | string | object) => Promise<void>
154
+ }) => Promise<void>,
155
+ logger: Logger
156
+ ): void {
157
+ this.runJob = runJob
158
+ this.logger = logger
159
+ }
146
160
 
147
161
  /**
148
162
  * Scan state and register all compatible processors
149
163
  */
150
164
  async registerQueues(): Promise<Record<string, ConfigValidationResult[]>> {
165
+ if (!this.runJob || !this.logger) {
166
+ throw new Error(
167
+ 'BullQueueWorkers requires setJobRunner() before registerQueues()'
168
+ )
169
+ }
170
+
151
171
  return await registerQueueWorkers(
152
172
  this.configMappings,
153
- this.singletonServices.logger,
173
+ this.logger,
154
174
  async (queueName, processor) => {
155
175
  const worker = new Worker(
156
- processor.queueName,
176
+ processor.name,
157
177
  async (job: Bull.Job) => {
158
178
  try {
159
- return await runQueueJob({
160
- singletonServices: this.singletonServices,
161
- createWireServices: this.createWireServices,
179
+ return await this.runJob!({
162
180
  job: await mapBullJobToQueueJob(
163
181
  job,
164
182
  this.redisConnectionOptions,
@@ -1,11 +1,13 @@
1
- import { ConnectionOptions, Queue } from 'bullmq'
1
+ import { ConnectionOptions, Queue, Worker } from 'bullmq'
2
2
  import {
3
3
  SchedulerService,
4
+ SchedulerRuntimeHandlers,
4
5
  ScheduledTaskInfo,
5
6
  ScheduledTaskSummary,
6
7
  CoreUserSession,
7
8
  parseDurationString,
8
9
  } from '@pikku/core'
10
+ import { getScheduledTasks } from '@pikku/core/scheduler'
9
11
 
10
12
  /**
11
13
  * Data stored in scheduled job
@@ -16,18 +18,32 @@ interface ScheduledJobData {
16
18
  session?: CoreUserSession
17
19
  }
18
20
 
19
- /**
20
- * BullMQ scheduler service implementation
21
- * Uses BullMQ's delayed jobs for one-time execution
22
- */
21
+ const RECURRING_QUEUE_NAME = 'pikku-recurring-scheduled-task'
22
+
23
23
  export class BullSchedulerService extends SchedulerService {
24
24
  private queue: Queue
25
+ private recurringQueue: Queue
26
+ private recurringWorker?: Worker
27
+ private repeatJobKeys: string[] = []
28
+ private handlers?: SchedulerRuntimeHandlers
25
29
 
26
- constructor(redisConnectionOptions: ConnectionOptions) {
30
+ constructor(private redisConnectionOptions: ConnectionOptions) {
27
31
  super()
28
32
  this.queue = new Queue('pikku-remote-internal-rpc', {
29
33
  connection: redisConnectionOptions,
30
34
  })
35
+ this.recurringQueue = new Queue(RECURRING_QUEUE_NAME, {
36
+ connection: redisConnectionOptions,
37
+ })
38
+ }
39
+
40
+ /**
41
+ * Set services needed for processing recurring tasks.
42
+ * Must be called before start() since the scheduler is typically
43
+ * created before singletonServices are available.
44
+ */
45
+ setServices(handlers: SchedulerRuntimeHandlers): void {
46
+ this.handlers = handlers
31
47
  }
32
48
 
33
49
  /**
@@ -134,6 +150,66 @@ export class BullSchedulerService extends SchedulerService {
134
150
  * Close the queue connection
135
151
  */
136
152
  async close(): Promise<void> {
153
+ if (this.recurringWorker) {
154
+ await this.recurringWorker.close()
155
+ }
156
+ await this.recurringQueue.close()
137
157
  await this.queue.close()
138
158
  }
159
+
160
+ /**
161
+ * Start recurring scheduled tasks.
162
+ * Creates a BullMQ Worker to process repeat jobs via runScheduledTask.
163
+ */
164
+ async start(): Promise<void> {
165
+ if (!this.handlers) {
166
+ throw new Error(
167
+ 'BullSchedulerService requires setServices() before start()'
168
+ )
169
+ }
170
+
171
+ const scheduledTasks = getScheduledTasks()
172
+
173
+ // Create a worker to process recurring scheduled task jobs
174
+ this.recurringWorker = new Worker(
175
+ RECURRING_QUEUE_NAME,
176
+ async (job) => {
177
+ const { rpcName } = job.data as ScheduledJobData
178
+ this.handlers!.logger.info(`Running scheduled task: ${rpcName}`)
179
+ await this.handlers!.runScheduledTask(rpcName)
180
+ },
181
+ { connection: this.redisConnectionOptions }
182
+ )
183
+ this.recurringWorker.on('error', (err) => {
184
+ this.handlers!.logger.error(`Recurring task worker error: ${err}`)
185
+ })
186
+
187
+ for (const [name, task] of scheduledTasks) {
188
+ const job = await this.recurringQueue.add(
189
+ name,
190
+ { rpcName: name } as ScheduledJobData,
191
+ {
192
+ repeat: { pattern: task.schedule },
193
+ jobId: `recurring:${name}`,
194
+ }
195
+ )
196
+ if (job.repeatJobKey) {
197
+ this.repeatJobKeys.push(job.repeatJobKey)
198
+ }
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Stop recurring scheduled tasks by removing repeat jobs.
204
+ */
205
+ async stop(): Promise<void> {
206
+ for (const key of this.repeatJobKeys) {
207
+ await this.recurringQueue.removeRepeatableByKey(key)
208
+ }
209
+ this.repeatJobKeys = []
210
+ if (this.recurringWorker) {
211
+ await this.recurringWorker.close()
212
+ this.recurringWorker = undefined
213
+ }
214
+ }
139
215
  }
@@ -3,6 +3,8 @@ import { BullQueueService } from './bull-queue-service.js'
3
3
  import { BullQueueWorkers } from './bull-queue-worker.js'
4
4
  import { BullSchedulerService } from './bull-scheduler-service.js'
5
5
  import type { CoreSingletonServices, CreateWireServices } from '@pikku/core'
6
+ import { createQueueJobRunner } from '@pikku/core/queue'
7
+ import { createSchedulerRuntimeHandlers } from '@pikku/core/scheduler'
6
8
 
7
9
  /**
8
10
  * Factory class for BullMQ services
@@ -40,12 +42,12 @@ export class BullServiceFactory {
40
42
  createWireServices?: CreateWireServices
41
43
  ): BullQueueWorkers {
42
44
  if (!this.queueWorkers) {
43
- this.queueWorkers = new BullQueueWorkers(
44
- this.redisConnectionOptions,
45
- singletonServices,
46
- createWireServices
47
- )
45
+ this.queueWorkers = new BullQueueWorkers(this.redisConnectionOptions)
48
46
  }
47
+ this.queueWorkers.setJobRunner(
48
+ createQueueJobRunner({ singletonServices, createWireServices }),
49
+ singletonServices.logger
50
+ )
49
51
  return this.queueWorkers
50
52
  }
51
53
 
@@ -61,6 +63,18 @@ export class BullServiceFactory {
61
63
  return this.schedulerService
62
64
  }
63
65
 
66
+ setSchedulerRuntime(
67
+ singletonServices: CoreSingletonServices,
68
+ createWireServices?: CreateWireServices
69
+ ): void {
70
+ this.getSchedulerService().setServices(
71
+ createSchedulerRuntimeHandlers({
72
+ singletonServices,
73
+ createWireServices,
74
+ })
75
+ )
76
+ }
77
+
64
78
  /**
65
79
  * Close all services
66
80
  */
package/src/utils.ts CHANGED
@@ -36,13 +36,14 @@ export const mapBullJobToQueueJob = async <In, Out>(
36
36
  result: bullJob.returnvalue as Out,
37
37
  status: async () => mapBullStateToStatus(await bullJob.getState()),
38
38
  waitForCompletion: async (ttl?: number): Promise<Out> => {
39
- let queueEvents = queueEventsMap.get(bullJob.name)
39
+ let queueEvents = queueEventsMap.get(bullJob.queueName)
40
40
  if (!queueEvents) {
41
41
  queueEvents = new QueueEvents(
42
- bullJob.name,
42
+ bullJob.queueName,
43
43
  redisConnection ? { connection: redisConnection } : undefined
44
44
  )
45
- queueEventsMap.set(bullJob.name, queueEvents)
45
+ queueEventsMap.set(bullJob.queueName, queueEvents)
46
+ await queueEvents.waitUntilReady()
46
47
  }
47
48
  return await bullJob.waitUntilFinished(queueEvents, ttl)
48
49
  },