@pikku/queue-bullmq 0.11.1 → 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,5 +1,24 @@
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
 
10
+ ## 0.11.2
11
+
12
+ ### Patch Changes
13
+
14
+ - db9c7bf: Simplify CreateWireServices type signature for custom Config compatibility
15
+ - Updated dependencies [db9c7bf]
16
+ - @pikku/core@0.11.2
17
+
18
+ ### Fixes
19
+
20
+ - ddd87eaf: Simplify CreateWireServices type signature for custom Config compatibility
21
+
3
22
  ## 0.11.1
4
23
 
5
24
  ### Patch Changes
@@ -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 { CoreServices, 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<CoreSingletonServices, CoreServices, any> | 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
  }
@@ -2,7 +2,7 @@ import { ConnectionOptions } from 'bullmq';
2
2
  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
- import type { CoreServices, CoreSingletonServices, CreateWireServices } from '@pikku/core';
5
+ import type { CoreSingletonServices, CreateWireServices } from '@pikku/core';
6
6
  /**
7
7
  * Factory class for BullMQ services
8
8
  * Manages Redis connection options shared across queue, worker, and scheduler services
@@ -24,13 +24,18 @@ export declare class BullServiceFactory {
24
24
  /**
25
25
  * Get the queue workers for processing jobs
26
26
  */
27
- getQueueWorkers(singletonServices: CoreSingletonServices, createWireServices?: CreateWireServices<CoreSingletonServices, CoreServices, any>): BullQueueWorkers;
27
+ getQueueWorkers(singletonServices: CoreSingletonServices, createWireServices?: CreateWireServices): BullQueueWorkers;
28
28
  /**
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
  */
35
36
  close(): Promise<void>;
37
+ /**
38
+ * Alias for close() - used by stopSingletonServices
39
+ */
40
+ stop(): Promise<void>;
36
41
  }
@@ -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
  */
@@ -62,4 +71,10 @@ export class BullServiceFactory {
62
71
  }
63
72
  await Promise.all(closePromises);
64
73
  }
74
+ /**
75
+ * Alias for close() - used by stopSingletonServices
76
+ */
77
+ async stop() {
78
+ await this.close();
79
+ }
65
80
  }
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.1",
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.1"
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,18 +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 {
20
- CoreServices,
21
- CoreSingletonServices,
22
- CreateWireServices,
23
- } from '@pikku/core'
19
+ import type { Logger } from '@pikku/core/services'
24
20
  import { mapBullJobToQueueJob } from './utils.js'
25
21
 
26
22
  export const mapPikkuWorkerToBull = (
@@ -141,32 +137,46 @@ export class BullQueueWorkers implements QueueWorkers {
141
137
 
142
138
  private workers = new Map<string, Bull.Worker>()
143
139
  private queueEvents = new Map<string, QueueEvents>()
144
-
145
- constructor(
146
- private redisConnectionOptions: ConnectionOptions,
147
- private singletonServices: CoreSingletonServices,
148
- private createWireServices?: CreateWireServices<
149
- CoreSingletonServices,
150
- CoreServices,
151
- any
152
- >
153
- ) {}
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
+ }
154
160
 
155
161
  /**
156
162
  * Scan state and register all compatible processors
157
163
  */
158
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
+
159
171
  return await registerQueueWorkers(
160
172
  this.configMappings,
161
- this.singletonServices.logger,
173
+ this.logger,
162
174
  async (queueName, processor) => {
163
175
  const worker = new Worker(
164
- processor.queueName,
176
+ processor.name,
165
177
  async (job: Bull.Job) => {
166
178
  try {
167
- return await runQueueJob({
168
- singletonServices: this.singletonServices,
169
- createWireServices: this.createWireServices,
179
+ return await this.runJob!({
170
180
  job: await mapBullJobToQueueJob(
171
181
  job,
172
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
  }
@@ -2,11 +2,9 @@ import { ConnectionOptions } from 'bullmq'
2
2
  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
- import type {
6
- CoreServices,
7
- CoreSingletonServices,
8
- CreateWireServices,
9
- } from '@pikku/core'
5
+ import type { CoreSingletonServices, CreateWireServices } from '@pikku/core'
6
+ import { createQueueJobRunner } from '@pikku/core/queue'
7
+ import { createSchedulerRuntimeHandlers } from '@pikku/core/scheduler'
10
8
 
11
9
  /**
12
10
  * Factory class for BullMQ services
@@ -41,19 +39,15 @@ export class BullServiceFactory {
41
39
  */
42
40
  getQueueWorkers(
43
41
  singletonServices: CoreSingletonServices,
44
- createWireServices?: CreateWireServices<
45
- CoreSingletonServices,
46
- CoreServices,
47
- any
48
- >
42
+ createWireServices?: CreateWireServices
49
43
  ): BullQueueWorkers {
50
44
  if (!this.queueWorkers) {
51
- this.queueWorkers = new BullQueueWorkers(
52
- this.redisConnectionOptions,
53
- singletonServices,
54
- createWireServices
55
- )
45
+ this.queueWorkers = new BullQueueWorkers(this.redisConnectionOptions)
56
46
  }
47
+ this.queueWorkers.setJobRunner(
48
+ createQueueJobRunner({ singletonServices, createWireServices }),
49
+ singletonServices.logger
50
+ )
57
51
  return this.queueWorkers
58
52
  }
59
53
 
@@ -69,6 +63,18 @@ export class BullServiceFactory {
69
63
  return this.schedulerService
70
64
  }
71
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
+
72
78
  /**
73
79
  * Close all services
74
80
  */
@@ -89,4 +95,11 @@ export class BullServiceFactory {
89
95
 
90
96
  await Promise.all(closePromises)
91
97
  }
98
+
99
+ /**
100
+ * Alias for close() - used by stopSingletonServices
101
+ */
102
+ async stop(): Promise<void> {
103
+ await this.close()
104
+ }
92
105
  }
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
  },