@pikku/queue-bullmq 0.12.0 → 0.12.1

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,23 @@
1
1
  ## 0.12.0
2
2
 
3
+ ## 0.12.1
4
+
5
+ ### Patch Changes
6
+
7
+ - e04531f: Code quality improvements: resolve oxlint warnings and apply autofixes across the codebase (unused bindings, unnecessary constructors, prefer `const` over `let`, etc.). No behaviour changes.
8
+ - Updated dependencies [62a8725]
9
+ - Updated dependencies [a3bdb0d]
10
+ - Updated dependencies [e0349ff]
11
+ - Updated dependencies [62a8725]
12
+ - Updated dependencies [e04531f]
13
+ - Updated dependencies [62a8725]
14
+ - Updated dependencies [a83efb8]
15
+ - Updated dependencies [8eed717]
16
+ - Updated dependencies [62a8725]
17
+ - Updated dependencies [62a8725]
18
+ - Updated dependencies [62a8725]
19
+ - @pikku/core@0.12.1
20
+
3
21
  ### New Features
4
22
 
5
23
  - Recurring cron scheduled tasks support via `BullSchedulerService`
@@ -1,4 +1,5 @@
1
- import Bull, { ConnectionOptions, JobsOptions } from 'bullmq';
1
+ import type { ConnectionOptions, JobsOptions } from 'bullmq';
2
+ import type Bull from 'bullmq';
2
3
  import type { QueueService, QueueJob, JobOptions } from '@pikku/core/queue';
3
4
  export declare const mapPikkuJobToBull: (options?: JobOptions) => JobsOptions;
4
5
  /**
@@ -1,4 +1,4 @@
1
- import { Queue, RedisConnection, } from 'bullmq';
1
+ import { Queue, QueueEvents, RedisConnection } from 'bullmq';
2
2
  import { mapBullJobToQueueJob } from './utils.js';
3
3
  export const mapPikkuJobToBull = (options) => {
4
4
  const bullOptions = {};
@@ -53,6 +53,13 @@ export class BullQueueService {
53
53
  const queue = new Queue(queueName, config, PikkuRedisConnection);
54
54
  await queue.waitUntilReady();
55
55
  this.queues.set(queueName, queue);
56
+ if (!this.queueEvents.has(queueName)) {
57
+ const queueEvents = new QueueEvents(queueName, this.redisConnectionOptions
58
+ ? { connection: this.redisConnectionOptions }
59
+ : undefined);
60
+ await queueEvents.waitUntilReady();
61
+ this.queueEvents.set(queueName, queueEvents);
62
+ }
56
63
  return queue;
57
64
  }
58
65
  /**
@@ -1,6 +1,5 @@
1
- import { ConnectionOptions, WorkerOptions } from 'bullmq';
2
- import type { QueueWorkers, PikkuWorkerConfig, QueueConfigMapping, ConfigValidationResult, QueueJob } from '@pikku/core/queue';
3
- import type { Logger } from '@pikku/core/services';
1
+ import type { ConnectionOptions, WorkerOptions } from 'bullmq';
2
+ import type { QueueWorkers, PikkuWorkerConfig, QueueConfigMapping, ConfigValidationResult } from '@pikku/core/queue';
4
3
  export declare const mapPikkuWorkerToBull: (workerConfig?: PikkuWorkerConfig) => Omit<WorkerOptions, "connection">;
5
4
  /**
6
5
  * Bull/Redis queue service implementation
@@ -17,13 +16,7 @@ export declare class BullQueueWorkers implements QueueWorkers {
17
16
  readonly configMappings: QueueConfigMapping;
18
17
  private workers;
19
18
  private queueEvents;
20
- private runJob?;
21
- private logger?;
22
19
  constructor(redisConnectionOptions: ConnectionOptions);
23
- setJobRunner(runJob: (params: {
24
- job: QueueJob;
25
- updateProgress?: (progress: number | string | object) => Promise<void>;
26
- }) => Promise<void>, logger: Logger): void;
27
20
  /**
28
21
  * Scan state and register all compatible processors
29
22
  */
@@ -1,5 +1,6 @@
1
- import { Worker, } from 'bullmq';
2
- import { registerQueueWorkers, QueueJobFailedError, QueueJobDiscardedError, } from '@pikku/core/queue';
1
+ import { Worker } from 'bullmq';
2
+ import { registerQueueWorkers, runQueueJob, QueueJobFailedError, QueueJobDiscardedError, } from '@pikku/core/queue';
3
+ import { pikkuState } from '@pikku/core/internal';
3
4
  import { mapBullJobToQueueJob } from './utils.js';
4
5
  export const mapPikkuWorkerToBull = (workerConfig) => {
5
6
  const workerOptions = {};
@@ -99,26 +100,18 @@ export class BullQueueWorkers {
99
100
  };
100
101
  workers = new Map();
101
102
  queueEvents = new Map();
102
- runJob;
103
- logger;
104
103
  constructor(redisConnectionOptions) {
105
104
  this.redisConnectionOptions = redisConnectionOptions;
106
105
  }
107
- setJobRunner(runJob, logger) {
108
- this.runJob = runJob;
109
- this.logger = logger;
110
- }
111
106
  /**
112
107
  * Scan state and register all compatible processors
113
108
  */
114
109
  async registerQueues() {
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) => {
110
+ const logger = pikkuState(null, 'package', 'singletonServices').logger;
111
+ return await registerQueueWorkers(this.configMappings, logger, async (queueName, processor) => {
119
112
  const worker = new Worker(processor.name, async (job) => {
120
113
  try {
121
- return await this.runJob({
114
+ return await runQueueJob({
122
115
  job: await mapBullJobToQueueJob(job, this.redisConnectionOptions, this.queueEvents),
123
116
  updateProgress: async (progress) => {
124
117
  await job.updateProgress(progress);
@@ -1,19 +1,13 @@
1
- import { ConnectionOptions } from 'bullmq';
2
- import { SchedulerService, SchedulerRuntimeHandlers, ScheduledTaskInfo, ScheduledTaskSummary, CoreUserSession } from '@pikku/core';
1
+ import type { ConnectionOptions } from 'bullmq';
2
+ import type { ScheduledTaskInfo, ScheduledTaskSummary, CoreUserSession } from '@pikku/core';
3
+ import { SchedulerService } from '@pikku/core';
3
4
  export declare class BullSchedulerService extends SchedulerService {
4
5
  private redisConnectionOptions;
5
6
  private queue;
6
7
  private recurringQueue;
7
8
  private recurringWorker?;
8
9
  private repeatJobKeys;
9
- private handlers?;
10
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;
17
11
  /**
18
12
  * Initialize - wait for queue to be ready
19
13
  */
@@ -1,6 +1,7 @@
1
1
  import { Queue, Worker } from 'bullmq';
2
- import { SchedulerService, parseDurationString, } from '@pikku/core';
3
- import { getScheduledTasks } from '@pikku/core/scheduler';
2
+ import { SchedulerService, parseDurationString } from '@pikku/core';
3
+ import { pikkuState } from '@pikku/core/internal';
4
+ import { runScheduledTask, getScheduledTasks } from '@pikku/core/scheduler';
4
5
  const RECURRING_QUEUE_NAME = 'pikku-recurring-scheduled-task';
5
6
  export class BullSchedulerService extends SchedulerService {
6
7
  redisConnectionOptions;
@@ -8,7 +9,6 @@ export class BullSchedulerService extends SchedulerService {
8
9
  recurringQueue;
9
10
  recurringWorker;
10
11
  repeatJobKeys = [];
11
- handlers;
12
12
  constructor(redisConnectionOptions) {
13
13
  super();
14
14
  this.redisConnectionOptions = redisConnectionOptions;
@@ -19,14 +19,6 @@ export class BullSchedulerService extends SchedulerService {
19
19
  connection: redisConnectionOptions,
20
20
  });
21
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;
29
- }
30
22
  /**
31
23
  * Initialize - wait for queue to be ready
32
24
  */
@@ -121,18 +113,16 @@ export class BullSchedulerService extends SchedulerService {
121
113
  * Creates a BullMQ Worker to process repeat jobs via runScheduledTask.
122
114
  */
123
115
  async start() {
124
- if (!this.handlers) {
125
- throw new Error('BullSchedulerService requires setServices() before start()');
126
- }
116
+ const logger = pikkuState(null, 'package', 'singletonServices').logger;
127
117
  const scheduledTasks = getScheduledTasks();
128
118
  // Create a worker to process recurring scheduled task jobs
129
119
  this.recurringWorker = new Worker(RECURRING_QUEUE_NAME, async (job) => {
130
120
  const { rpcName } = job.data;
131
- this.handlers.logger.info(`Running scheduled task: ${rpcName}`);
132
- await this.handlers.runScheduledTask(rpcName);
121
+ logger.info(`Running scheduled task: ${rpcName}`);
122
+ await runScheduledTask({ name: rpcName });
133
123
  }, { connection: this.redisConnectionOptions });
134
124
  this.recurringWorker.on('error', (err) => {
135
- this.handlers.logger.error(`Recurring task worker error: ${err}`);
125
+ logger.error(`Recurring task worker error: ${err}`);
136
126
  });
137
127
  for (const [name, task] of scheduledTasks) {
138
128
  const job = await this.recurringQueue.add(name, { rpcName: name }, {
@@ -1,8 +1,7 @@
1
- import { ConnectionOptions } from 'bullmq';
1
+ import type { 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 { CoreSingletonServices, CreateWireServices } from '@pikku/core';
6
5
  /**
7
6
  * Factory class for BullMQ services
8
7
  * Manages Redis connection options shared across queue, worker, and scheduler services
@@ -24,12 +23,11 @@ export declare class BullServiceFactory {
24
23
  /**
25
24
  * Get the queue workers for processing jobs
26
25
  */
27
- getQueueWorkers(singletonServices: CoreSingletonServices, createWireServices?: CreateWireServices): BullQueueWorkers;
26
+ getQueueWorkers(): BullQueueWorkers;
28
27
  /**
29
28
  * Get the scheduler service for managing delayed tasks
30
29
  */
31
30
  getSchedulerService(): BullSchedulerService;
32
- setSchedulerRuntime(singletonServices: CoreSingletonServices, createWireServices?: CreateWireServices): void;
33
31
  /**
34
32
  * Close all services
35
33
  */
@@ -1,8 +1,6 @@
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';
6
4
  /**
7
5
  * Factory class for BullMQ services
8
6
  * Manages Redis connection options shared across queue, worker, and scheduler services
@@ -33,11 +31,10 @@ export class BullServiceFactory {
33
31
  /**
34
32
  * Get the queue workers for processing jobs
35
33
  */
36
- getQueueWorkers(singletonServices, createWireServices) {
34
+ getQueueWorkers() {
37
35
  if (!this.queueWorkers) {
38
36
  this.queueWorkers = new BullQueueWorkers(this.redisConnectionOptions);
39
37
  }
40
- this.queueWorkers.setJobRunner(createQueueJobRunner({ singletonServices, createWireServices }), singletonServices.logger);
41
38
  return this.queueWorkers;
42
39
  }
43
40
  /**
@@ -49,12 +46,6 @@ export class BullServiceFactory {
49
46
  }
50
47
  return this.schedulerService;
51
48
  }
52
- setSchedulerRuntime(singletonServices, createWireServices) {
53
- this.getSchedulerService().setServices(createSchedulerRuntimeHandlers({
54
- singletonServices,
55
- createWireServices,
56
- }));
57
- }
58
49
  /**
59
50
  * Close all services
60
51
  */
package/dist/utils.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { QueueJob } from '@pikku/core/queue';
2
- import { ConnectionOptions, Job, QueueEvents } from 'bullmq';
1
+ import type { QueueJob } from '@pikku/core/queue';
2
+ import type { ConnectionOptions, Job } from 'bullmq';
3
+ import { QueueEvents } from 'bullmq';
3
4
  /**
4
5
  * Map Bull job to QueueJob interface
5
6
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/queue-bullmq",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "MIT",
6
6
  "module": "dist/index.js",
@@ -13,7 +13,7 @@
13
13
  "release": "npm run build && npm test"
14
14
  },
15
15
  "peerDependencies": {
16
- "@pikku/core": "^0.12.0"
16
+ "@pikku/core": "^0.12.1"
17
17
  },
18
18
  "dependencies": {
19
19
  "bullmq": "^5.67.3",
@@ -1,9 +1,6 @@
1
- import Bull, {
2
- ConnectionOptions,
3
- JobsOptions,
4
- Queue,
5
- RedisConnection,
6
- } from 'bullmq'
1
+ import type { ConnectionOptions, JobsOptions } from 'bullmq'
2
+ import type Bull from 'bullmq'
3
+ import { Queue, QueueEvents, RedisConnection } from 'bullmq'
7
4
  import type { QueueService, QueueJob, JobOptions } from '@pikku/core/queue'
8
5
  import { mapBullJobToQueueJob } from './utils.js'
9
6
 
@@ -73,6 +70,18 @@ export class BullQueueService implements QueueService {
73
70
  await queue.waitUntilReady()
74
71
 
75
72
  this.queues.set(queueName, queue)
73
+
74
+ if (!this.queueEvents.has(queueName)) {
75
+ const queueEvents = new QueueEvents(
76
+ queueName,
77
+ this.redisConnectionOptions
78
+ ? { connection: this.redisConnectionOptions }
79
+ : undefined
80
+ )
81
+ await queueEvents.waitUntilReady()
82
+ this.queueEvents.set(queueName, queueEvents)
83
+ }
84
+
76
85
  return queue
77
86
  }
78
87
 
@@ -1,22 +1,19 @@
1
- import Bull, {
2
- ConnectionOptions,
3
- WorkerOptions,
4
- Worker,
5
- QueueEvents,
6
- } from 'bullmq'
1
+ import type { ConnectionOptions, WorkerOptions, QueueEvents } from 'bullmq'
2
+ import type Bull from 'bullmq'
3
+ import { Worker } from 'bullmq'
7
4
  import type {
8
5
  QueueWorkers,
9
6
  PikkuWorkerConfig,
10
7
  QueueConfigMapping,
11
8
  ConfigValidationResult,
12
- QueueJob,
13
9
  } from '@pikku/core/queue'
14
10
  import {
15
11
  registerQueueWorkers,
12
+ runQueueJob,
16
13
  QueueJobFailedError,
17
14
  QueueJobDiscardedError,
18
15
  } from '@pikku/core/queue'
19
- import type { Logger } from '@pikku/core/services'
16
+ import { pikkuState } from '@pikku/core/internal'
20
17
  import { mapBullJobToQueueJob } from './utils.js'
21
18
 
22
19
  export const mapPikkuWorkerToBull = (
@@ -137,46 +134,24 @@ export class BullQueueWorkers implements QueueWorkers {
137
134
 
138
135
  private workers = new Map<string, Bull.Worker>()
139
136
  private queueEvents = new Map<string, QueueEvents>()
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
137
 
148
138
  constructor(private redisConnectionOptions: ConnectionOptions) {}
149
139
 
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
- }
160
-
161
140
  /**
162
141
  * Scan state and register all compatible processors
163
142
  */
164
143
  async registerQueues(): Promise<Record<string, ConfigValidationResult[]>> {
165
- if (!this.runJob || !this.logger) {
166
- throw new Error(
167
- 'BullQueueWorkers requires setJobRunner() before registerQueues()'
168
- )
169
- }
144
+ const logger = pikkuState(null, 'package', 'singletonServices')!.logger
170
145
 
171
146
  return await registerQueueWorkers(
172
147
  this.configMappings,
173
- this.logger,
148
+ logger,
174
149
  async (queueName, processor) => {
175
150
  const worker = new Worker(
176
151
  processor.name,
177
152
  async (job: Bull.Job) => {
178
153
  try {
179
- return await this.runJob!({
154
+ return await runQueueJob({
180
155
  job: await mapBullJobToQueueJob(
181
156
  job,
182
157
  this.redisConnectionOptions,
@@ -1,13 +1,13 @@
1
- import { ConnectionOptions, Queue, Worker } from 'bullmq'
2
- import {
3
- SchedulerService,
4
- SchedulerRuntimeHandlers,
1
+ import type { ConnectionOptions } from 'bullmq'
2
+ import { Queue, Worker } from 'bullmq'
3
+ import type {
5
4
  ScheduledTaskInfo,
6
5
  ScheduledTaskSummary,
7
6
  CoreUserSession,
8
- parseDurationString,
9
7
  } from '@pikku/core'
10
- import { getScheduledTasks } from '@pikku/core/scheduler'
8
+ import { SchedulerService, parseDurationString } from '@pikku/core'
9
+ import { pikkuState } from '@pikku/core/internal'
10
+ import { runScheduledTask, getScheduledTasks } from '@pikku/core/scheduler'
11
11
 
12
12
  /**
13
13
  * Data stored in scheduled job
@@ -25,7 +25,6 @@ export class BullSchedulerService extends SchedulerService {
25
25
  private recurringQueue: Queue
26
26
  private recurringWorker?: Worker
27
27
  private repeatJobKeys: string[] = []
28
- private handlers?: SchedulerRuntimeHandlers
29
28
 
30
29
  constructor(private redisConnectionOptions: ConnectionOptions) {
31
30
  super()
@@ -37,15 +36,6 @@ export class BullSchedulerService extends SchedulerService {
37
36
  })
38
37
  }
39
38
 
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
47
- }
48
-
49
39
  /**
50
40
  * Initialize - wait for queue to be ready
51
41
  */
@@ -162,12 +152,7 @@ export class BullSchedulerService extends SchedulerService {
162
152
  * Creates a BullMQ Worker to process repeat jobs via runScheduledTask.
163
153
  */
164
154
  async start(): Promise<void> {
165
- if (!this.handlers) {
166
- throw new Error(
167
- 'BullSchedulerService requires setServices() before start()'
168
- )
169
- }
170
-
155
+ const logger = pikkuState(null, 'package', 'singletonServices')!.logger
171
156
  const scheduledTasks = getScheduledTasks()
172
157
 
173
158
  // Create a worker to process recurring scheduled task jobs
@@ -175,13 +160,13 @@ export class BullSchedulerService extends SchedulerService {
175
160
  RECURRING_QUEUE_NAME,
176
161
  async (job) => {
177
162
  const { rpcName } = job.data as ScheduledJobData
178
- this.handlers!.logger.info(`Running scheduled task: ${rpcName}`)
179
- await this.handlers!.runScheduledTask(rpcName)
163
+ logger.info(`Running scheduled task: ${rpcName}`)
164
+ await runScheduledTask({ name: rpcName })
180
165
  },
181
166
  { connection: this.redisConnectionOptions }
182
167
  )
183
168
  this.recurringWorker.on('error', (err) => {
184
- this.handlers!.logger.error(`Recurring task worker error: ${err}`)
169
+ logger.error(`Recurring task worker error: ${err}`)
185
170
  })
186
171
 
187
172
  for (const [name, task] of scheduledTasks) {
@@ -1,10 +1,7 @@
1
- import { ConnectionOptions } from 'bullmq'
1
+ import type { 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 { CoreSingletonServices, CreateWireServices } from '@pikku/core'
6
- import { createQueueJobRunner } from '@pikku/core/queue'
7
- import { createSchedulerRuntimeHandlers } from '@pikku/core/scheduler'
8
5
 
9
6
  /**
10
7
  * Factory class for BullMQ services
@@ -37,17 +34,10 @@ export class BullServiceFactory {
37
34
  /**
38
35
  * Get the queue workers for processing jobs
39
36
  */
40
- getQueueWorkers(
41
- singletonServices: CoreSingletonServices,
42
- createWireServices?: CreateWireServices
43
- ): BullQueueWorkers {
37
+ getQueueWorkers(): BullQueueWorkers {
44
38
  if (!this.queueWorkers) {
45
39
  this.queueWorkers = new BullQueueWorkers(this.redisConnectionOptions)
46
40
  }
47
- this.queueWorkers.setJobRunner(
48
- createQueueJobRunner({ singletonServices, createWireServices }),
49
- singletonServices.logger
50
- )
51
41
  return this.queueWorkers
52
42
  }
53
43
 
@@ -63,18 +53,6 @@ export class BullServiceFactory {
63
53
  return this.schedulerService
64
54
  }
65
55
 
66
- setSchedulerRuntime(
67
- singletonServices: CoreSingletonServices,
68
- createWireServices?: CreateWireServices
69
- ): void {
70
- this.getSchedulerService().setServices(
71
- createSchedulerRuntimeHandlers({
72
- singletonServices,
73
- createWireServices,
74
- })
75
- )
76
- }
77
-
78
56
  /**
79
57
  * Close all services
80
58
  */
package/src/utils.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { QueueJob, QueueJobStatus } from '@pikku/core/queue'
2
- import { ConnectionOptions, Job, QueueEvents } from 'bullmq'
1
+ import type { QueueJob, QueueJobStatus } from '@pikku/core/queue'
2
+ import type { ConnectionOptions, Job } from 'bullmq'
3
+ import { QueueEvents } from 'bullmq'
3
4
 
4
5
  /**
5
6
  * Map Bull job state to our queue job status