@pikku/queue-bullmq 0.10.0 → 0.11.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,3 +1,24 @@
1
+ ## 0.11.0
2
+
3
+ ## 0.11.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 4b811db: chore: updating all dependencies
8
+ - 06e1a31: breaking: change session services to wire services
9
+ - Updated dependencies [4b811db]
10
+ - Updated dependencies [e12a00c]
11
+ - Updated dependencies [4579434]
12
+ - Updated dependencies [28aeb7f]
13
+ - Updated dependencies [ce902b1]
14
+ - Updated dependencies [06e1a31]
15
+ - @pikku/core@0.11.1
16
+
17
+ ### Minor Changes
18
+
19
+ - Add scheduler service implementation
20
+ - Add service factory for queue and scheduler creation
21
+
1
22
  # @pikku/queue-bullmq
2
23
 
3
24
  ## 0.10.0
@@ -1,6 +1,6 @@
1
1
  import { ConnectionOptions, WorkerOptions } from 'bullmq';
2
2
  import type { QueueWorkers, PikkuWorkerConfig, QueueConfigMapping, ConfigValidationResult } from '@pikku/core/queue';
3
- import { CoreServices, CoreSingletonServices, CreateSessionServices } from '@pikku/core';
3
+ import type { CoreServices, CoreSingletonServices, CreateWireServices } from '@pikku/core';
4
4
  export declare const mapPikkuWorkerToBull: (workerConfig?: PikkuWorkerConfig) => Omit<WorkerOptions, "connection">;
5
5
  /**
6
6
  * Bull/Redis queue service implementation
@@ -9,7 +9,7 @@ export declare const mapPikkuWorkerToBull: (workerConfig?: PikkuWorkerConfig) =>
9
9
  export declare class BullQueueWorkers implements QueueWorkers {
10
10
  private redisConnectionOptions;
11
11
  private singletonServices;
12
- private createSessionServices?;
12
+ private createWireServices?;
13
13
  readonly name = "bull";
14
14
  readonly supportsResults = true;
15
15
  /**
@@ -19,7 +19,7 @@ export declare class BullQueueWorkers implements QueueWorkers {
19
19
  readonly configMappings: QueueConfigMapping;
20
20
  private workers;
21
21
  private queueEvents;
22
- constructor(redisConnectionOptions: ConnectionOptions, singletonServices: CoreSingletonServices, createSessionServices?: CreateSessionServices<CoreSingletonServices, CoreServices, any> | undefined);
22
+ constructor(redisConnectionOptions: ConnectionOptions, singletonServices: CoreSingletonServices, createWireServices?: CreateWireServices<CoreSingletonServices, CoreServices, any> | undefined);
23
23
  /**
24
24
  * Scan state and register all compatible processors
25
25
  */
@@ -38,7 +38,7 @@ export const mapPikkuWorkerToBull = (workerConfig) => {
38
38
  export class BullQueueWorkers {
39
39
  redisConnectionOptions;
40
40
  singletonServices;
41
- createSessionServices;
41
+ createWireServices;
42
42
  name = 'bull';
43
43
  supportsResults = true;
44
44
  /**
@@ -101,10 +101,10 @@ export class BullQueueWorkers {
101
101
  };
102
102
  workers = new Map();
103
103
  queueEvents = new Map();
104
- constructor(redisConnectionOptions, singletonServices, createSessionServices) {
104
+ constructor(redisConnectionOptions, singletonServices, createWireServices) {
105
105
  this.redisConnectionOptions = redisConnectionOptions;
106
106
  this.singletonServices = singletonServices;
107
- this.createSessionServices = createSessionServices;
107
+ this.createWireServices = createWireServices;
108
108
  }
109
109
  /**
110
110
  * Scan state and register all compatible processors
@@ -115,7 +115,7 @@ export class BullQueueWorkers {
115
115
  try {
116
116
  return await runQueueJob({
117
117
  singletonServices: this.singletonServices,
118
- createSessionServices: this.createSessionServices,
118
+ createWireServices: this.createWireServices,
119
119
  job: await mapBullJobToQueueJob(job, this.redisConnectionOptions, this.queueEvents),
120
120
  updateProgress: async (progress) => {
121
121
  await job.updateProgress(progress);
@@ -0,0 +1,35 @@
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
+ */
7
+ export declare class BullSchedulerService extends SchedulerService {
8
+ private queue;
9
+ constructor(redisConnectionOptions: ConnectionOptions);
10
+ /**
11
+ * Initialize - wait for queue to be ready
12
+ */
13
+ init(): Promise<void>;
14
+ /**
15
+ * Schedule a one-off delayed RPC call
16
+ * Uses BullMQ add() with delay option
17
+ */
18
+ scheduleRPC(delay: number | string, rpcName: string, data?: any, session?: CoreUserSession): Promise<string>;
19
+ /**
20
+ * Unschedule (remove) a task by ID
21
+ */
22
+ unschedule(taskId: string): Promise<boolean>;
23
+ /**
24
+ * Get a scheduled task by ID with full details
25
+ */
26
+ getTask(taskId: string): Promise<ScheduledTaskInfo | null>;
27
+ /**
28
+ * Get all scheduled tasks with minimal info
29
+ */
30
+ getAllTasks(): Promise<ScheduledTaskSummary[]>;
31
+ /**
32
+ * Close the queue connection
33
+ */
34
+ close(): Promise<void>;
35
+ }
@@ -0,0 +1,100 @@
1
+ import { Queue } from 'bullmq';
2
+ import { SchedulerService, parseDurationString, } from '@pikku/core';
3
+ /**
4
+ * BullMQ scheduler service implementation
5
+ * Uses BullMQ's delayed jobs for one-time execution
6
+ */
7
+ export class BullSchedulerService extends SchedulerService {
8
+ queue;
9
+ constructor(redisConnectionOptions) {
10
+ super();
11
+ this.queue = new Queue('pikku-remote-internal-rpc', {
12
+ connection: redisConnectionOptions,
13
+ });
14
+ }
15
+ /**
16
+ * Initialize - wait for queue to be ready
17
+ */
18
+ async init() {
19
+ await this.queue.waitUntilReady();
20
+ }
21
+ /**
22
+ * Schedule a one-off delayed RPC call
23
+ * Uses BullMQ add() with delay option
24
+ */
25
+ async scheduleRPC(delay, rpcName, data, session) {
26
+ // Parse delay if it's a string
27
+ const delayMs = typeof delay === 'string' ? parseDurationString(delay) : delay;
28
+ const jobData = {
29
+ rpcName,
30
+ data,
31
+ session,
32
+ };
33
+ // Use add() with delay for one-off delayed execution
34
+ const job = await this.queue.add('pikku-remote-internal-rpc', jobData, {
35
+ delay: delayMs, // delay in milliseconds
36
+ jobId: `${rpcName}-${Date.now()}`, // Ensure uniqueness
37
+ });
38
+ if (!job.id) {
39
+ throw new Error('Failed to schedule RPC');
40
+ }
41
+ return job.id;
42
+ }
43
+ /**
44
+ * Unschedule (remove) a task by ID
45
+ */
46
+ async unschedule(taskId) {
47
+ const job = await this.queue.getJob(taskId);
48
+ if (job) {
49
+ await job.remove();
50
+ return true;
51
+ }
52
+ return false;
53
+ }
54
+ /**
55
+ * Get a scheduled task by ID with full details
56
+ */
57
+ async getTask(taskId) {
58
+ const job = await this.queue.getJob(taskId);
59
+ if (!job) {
60
+ return null;
61
+ }
62
+ const jobData = job.data;
63
+ const state = await job.getState();
64
+ // Calculate scheduled time from delay or processedOn
65
+ const scheduledFor = job.delay
66
+ ? new Date(job.timestamp + job.delay)
67
+ : new Date(job.timestamp);
68
+ return {
69
+ taskId: job.id,
70
+ rpcName: jobData.rpcName,
71
+ scheduledFor,
72
+ data: jobData.data,
73
+ session: jobData.session,
74
+ status: state,
75
+ };
76
+ }
77
+ /**
78
+ * Get all scheduled tasks with minimal info
79
+ */
80
+ async getAllTasks() {
81
+ const jobs = await this.queue.getJobs(['delayed', 'waiting']);
82
+ return jobs.map((job) => {
83
+ const jobData = job.data;
84
+ const scheduledFor = job.delay
85
+ ? new Date(job.timestamp + job.delay)
86
+ : new Date(job.timestamp);
87
+ return {
88
+ taskId: job.id,
89
+ rpcName: jobData.rpcName,
90
+ scheduledFor,
91
+ };
92
+ });
93
+ }
94
+ /**
95
+ * Close the queue connection
96
+ */
97
+ async close() {
98
+ await this.queue.close();
99
+ }
100
+ }
@@ -0,0 +1,36 @@
1
+ import { ConnectionOptions } from 'bullmq';
2
+ import { BullQueueService } from './bull-queue-service.js';
3
+ import { BullQueueWorkers } from './bull-queue-worker.js';
4
+ import { BullSchedulerService } from './bull-scheduler-service.js';
5
+ import type { CoreServices, CoreSingletonServices, CreateWireServices } from '@pikku/core';
6
+ /**
7
+ * Factory class for BullMQ services
8
+ * Manages Redis connection options shared across queue, worker, and scheduler services
9
+ */
10
+ export declare class BullServiceFactory {
11
+ private redisConnectionOptions;
12
+ private queueService?;
13
+ private queueWorkers?;
14
+ private schedulerService?;
15
+ constructor(redisConnectionOptions?: ConnectionOptions);
16
+ /**
17
+ * Initialize - no-op for BullMQ as connections are lazy
18
+ */
19
+ init(): Promise<void>;
20
+ /**
21
+ * Get the queue service for publishing jobs
22
+ */
23
+ getQueueService(): BullQueueService;
24
+ /**
25
+ * Get the queue workers for processing jobs
26
+ */
27
+ getQueueWorkers(singletonServices: CoreSingletonServices, createWireServices?: CreateWireServices<CoreSingletonServices, CoreServices, any>): BullQueueWorkers;
28
+ /**
29
+ * Get the scheduler service for managing delayed tasks
30
+ */
31
+ getSchedulerService(): BullSchedulerService;
32
+ /**
33
+ * Close all services
34
+ */
35
+ close(): Promise<void>;
36
+ }
@@ -0,0 +1,65 @@
1
+ import { BullQueueService } from './bull-queue-service.js';
2
+ import { BullQueueWorkers } from './bull-queue-worker.js';
3
+ import { BullSchedulerService } from './bull-scheduler-service.js';
4
+ /**
5
+ * Factory class for BullMQ services
6
+ * Manages Redis connection options shared across queue, worker, and scheduler services
7
+ */
8
+ export class BullServiceFactory {
9
+ redisConnectionOptions;
10
+ queueService;
11
+ queueWorkers;
12
+ schedulerService;
13
+ constructor(redisConnectionOptions = {}) {
14
+ this.redisConnectionOptions = redisConnectionOptions;
15
+ }
16
+ /**
17
+ * Initialize - no-op for BullMQ as connections are lazy
18
+ */
19
+ async init() {
20
+ // No-op - BullMQ creates connections lazily
21
+ }
22
+ /**
23
+ * Get the queue service for publishing jobs
24
+ */
25
+ getQueueService() {
26
+ if (!this.queueService) {
27
+ this.queueService = new BullQueueService(this.redisConnectionOptions);
28
+ }
29
+ return this.queueService;
30
+ }
31
+ /**
32
+ * Get the queue workers for processing jobs
33
+ */
34
+ getQueueWorkers(singletonServices, createWireServices) {
35
+ if (!this.queueWorkers) {
36
+ this.queueWorkers = new BullQueueWorkers(this.redisConnectionOptions, singletonServices, createWireServices);
37
+ }
38
+ return this.queueWorkers;
39
+ }
40
+ /**
41
+ * Get the scheduler service for managing delayed tasks
42
+ */
43
+ getSchedulerService() {
44
+ if (!this.schedulerService) {
45
+ this.schedulerService = new BullSchedulerService(this.redisConnectionOptions);
46
+ }
47
+ return this.schedulerService;
48
+ }
49
+ /**
50
+ * Close all services
51
+ */
52
+ async close() {
53
+ const closePromises = [];
54
+ if (this.queueService) {
55
+ // BullQueueService doesn't have close method currently
56
+ }
57
+ if (this.queueWorkers) {
58
+ closePromises.push(this.queueWorkers.close());
59
+ }
60
+ if (this.schedulerService) {
61
+ closePromises.push(this.schedulerService.close());
62
+ }
63
+ await Promise.all(closePromises);
64
+ }
65
+ }
package/dist/index.d.ts CHANGED
@@ -4,6 +4,8 @@
4
4
  * Bull/Redis queue service for Pikku
5
5
  * Provides job results, retries, priorities, and most queue features
6
6
  */
7
+ export { BullServiceFactory } from './bull-service-factory.js';
7
8
  export { BullQueueService } from './bull-queue-service.js';
8
9
  export { BullQueueWorkers } from './bull-queue-worker.js';
10
+ export { BullSchedulerService } from './bull-scheduler-service.js';
9
11
  export type { QueueService, PikkuWorkerConfig, PikkuJobConfig, QueueJob, JobOptions, } from '@pikku/core/queue';
package/dist/index.js CHANGED
@@ -4,5 +4,7 @@
4
4
  * Bull/Redis queue service for Pikku
5
5
  * Provides job results, retries, priorities, and most queue features
6
6
  */
7
+ export { BullServiceFactory } from './bull-service-factory.js';
7
8
  export { BullQueueService } from './bull-queue-service.js';
8
9
  export { BullQueueWorkers } from './bull-queue-worker.js';
10
+ export { BullSchedulerService } from './bull-scheduler-service.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/queue-bullmq",
3
- "version": "0.10.0",
3
+ "version": "0.11.1",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "MIT",
6
6
  "module": "dist/index.js",
@@ -13,10 +13,10 @@
13
13
  "release": "npm run build && npm test"
14
14
  },
15
15
  "peerDependencies": {
16
- "@pikku/core": "^0.10.0"
16
+ "@pikku/core": "^0.11.1"
17
17
  },
18
18
  "dependencies": {
19
- "bullmq": "^5.61.0",
19
+ "bullmq": "^5.63.2",
20
20
  "ioredis": "^5.8.2"
21
21
  },
22
22
  "devDependencies": {
@@ -16,10 +16,10 @@ import {
16
16
  QueueJobFailedError,
17
17
  QueueJobDiscardedError,
18
18
  } from '@pikku/core/queue'
19
- import {
19
+ import type {
20
20
  CoreServices,
21
21
  CoreSingletonServices,
22
- CreateSessionServices,
22
+ CreateWireServices,
23
23
  } from '@pikku/core'
24
24
  import { mapBullJobToQueueJob } from './utils.js'
25
25
 
@@ -145,7 +145,7 @@ export class BullQueueWorkers implements QueueWorkers {
145
145
  constructor(
146
146
  private redisConnectionOptions: ConnectionOptions,
147
147
  private singletonServices: CoreSingletonServices,
148
- private createSessionServices?: CreateSessionServices<
148
+ private createWireServices?: CreateWireServices<
149
149
  CoreSingletonServices,
150
150
  CoreServices,
151
151
  any
@@ -166,7 +166,7 @@ export class BullQueueWorkers implements QueueWorkers {
166
166
  try {
167
167
  return await runQueueJob({
168
168
  singletonServices: this.singletonServices,
169
- createSessionServices: this.createSessionServices,
169
+ createWireServices: this.createWireServices,
170
170
  job: await mapBullJobToQueueJob(
171
171
  job,
172
172
  this.redisConnectionOptions,
@@ -0,0 +1,139 @@
1
+ import { ConnectionOptions, Queue } from 'bullmq'
2
+ import {
3
+ SchedulerService,
4
+ ScheduledTaskInfo,
5
+ ScheduledTaskSummary,
6
+ CoreUserSession,
7
+ parseDurationString,
8
+ } from '@pikku/core'
9
+
10
+ /**
11
+ * Data stored in scheduled job
12
+ */
13
+ interface ScheduledJobData {
14
+ rpcName: string
15
+ data?: any
16
+ session?: CoreUserSession
17
+ }
18
+
19
+ /**
20
+ * BullMQ scheduler service implementation
21
+ * Uses BullMQ's delayed jobs for one-time execution
22
+ */
23
+ export class BullSchedulerService extends SchedulerService {
24
+ private queue: Queue
25
+
26
+ constructor(redisConnectionOptions: ConnectionOptions) {
27
+ super()
28
+ this.queue = new Queue('pikku-remote-internal-rpc', {
29
+ connection: redisConnectionOptions,
30
+ })
31
+ }
32
+
33
+ /**
34
+ * Initialize - wait for queue to be ready
35
+ */
36
+ async init(): Promise<void> {
37
+ await this.queue.waitUntilReady()
38
+ }
39
+
40
+ /**
41
+ * Schedule a one-off delayed RPC call
42
+ * Uses BullMQ add() with delay option
43
+ */
44
+ async scheduleRPC(
45
+ delay: number | string,
46
+ rpcName: string,
47
+ data?: any,
48
+ session?: CoreUserSession
49
+ ): Promise<string> {
50
+ // Parse delay if it's a string
51
+ const delayMs =
52
+ typeof delay === 'string' ? parseDurationString(delay) : delay
53
+
54
+ const jobData: ScheduledJobData = {
55
+ rpcName,
56
+ data,
57
+ session,
58
+ }
59
+
60
+ // Use add() with delay for one-off delayed execution
61
+ const job = await this.queue.add('pikku-remote-internal-rpc', jobData, {
62
+ delay: delayMs, // delay in milliseconds
63
+ jobId: `${rpcName}-${Date.now()}`, // Ensure uniqueness
64
+ })
65
+
66
+ if (!job.id) {
67
+ throw new Error('Failed to schedule RPC')
68
+ }
69
+
70
+ return job.id
71
+ }
72
+
73
+ /**
74
+ * Unschedule (remove) a task by ID
75
+ */
76
+ async unschedule(taskId: string): Promise<boolean> {
77
+ const job = await this.queue.getJob(taskId)
78
+ if (job) {
79
+ await job.remove()
80
+ return true
81
+ }
82
+ return false
83
+ }
84
+
85
+ /**
86
+ * Get a scheduled task by ID with full details
87
+ */
88
+ async getTask(taskId: string): Promise<ScheduledTaskInfo | null> {
89
+ const job = await this.queue.getJob(taskId)
90
+
91
+ if (!job) {
92
+ return null
93
+ }
94
+
95
+ const jobData = job.data as ScheduledJobData
96
+ const state = await job.getState()
97
+
98
+ // Calculate scheduled time from delay or processedOn
99
+ const scheduledFor = job.delay
100
+ ? new Date(job.timestamp + job.delay)
101
+ : new Date(job.timestamp)
102
+
103
+ return {
104
+ taskId: job.id!,
105
+ rpcName: jobData.rpcName,
106
+ scheduledFor,
107
+ data: jobData.data,
108
+ session: jobData.session,
109
+ status: state as any,
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Get all scheduled tasks with minimal info
115
+ */
116
+ async getAllTasks(): Promise<ScheduledTaskSummary[]> {
117
+ const jobs = await this.queue.getJobs(['delayed', 'waiting'])
118
+
119
+ return jobs.map((job) => {
120
+ const jobData = job.data as ScheduledJobData
121
+ const scheduledFor = job.delay
122
+ ? new Date(job.timestamp + job.delay)
123
+ : new Date(job.timestamp)
124
+
125
+ return {
126
+ taskId: job.id!,
127
+ rpcName: jobData.rpcName,
128
+ scheduledFor,
129
+ }
130
+ })
131
+ }
132
+
133
+ /**
134
+ * Close the queue connection
135
+ */
136
+ async close(): Promise<void> {
137
+ await this.queue.close()
138
+ }
139
+ }
@@ -0,0 +1,92 @@
1
+ import { ConnectionOptions } from 'bullmq'
2
+ import { BullQueueService } from './bull-queue-service.js'
3
+ import { BullQueueWorkers } from './bull-queue-worker.js'
4
+ import { BullSchedulerService } from './bull-scheduler-service.js'
5
+ import type {
6
+ CoreServices,
7
+ CoreSingletonServices,
8
+ CreateWireServices,
9
+ } from '@pikku/core'
10
+
11
+ /**
12
+ * Factory class for BullMQ services
13
+ * Manages Redis connection options shared across queue, worker, and scheduler services
14
+ */
15
+ export class BullServiceFactory {
16
+ private queueService?: BullQueueService
17
+ private queueWorkers?: BullQueueWorkers
18
+ private schedulerService?: BullSchedulerService
19
+
20
+ constructor(private redisConnectionOptions: ConnectionOptions = {}) {}
21
+
22
+ /**
23
+ * Initialize - no-op for BullMQ as connections are lazy
24
+ */
25
+ async init(): Promise<void> {
26
+ // No-op - BullMQ creates connections lazily
27
+ }
28
+
29
+ /**
30
+ * Get the queue service for publishing jobs
31
+ */
32
+ getQueueService(): BullQueueService {
33
+ if (!this.queueService) {
34
+ this.queueService = new BullQueueService(this.redisConnectionOptions)
35
+ }
36
+ return this.queueService
37
+ }
38
+
39
+ /**
40
+ * Get the queue workers for processing jobs
41
+ */
42
+ getQueueWorkers(
43
+ singletonServices: CoreSingletonServices,
44
+ createWireServices?: CreateWireServices<
45
+ CoreSingletonServices,
46
+ CoreServices,
47
+ any
48
+ >
49
+ ): BullQueueWorkers {
50
+ if (!this.queueWorkers) {
51
+ this.queueWorkers = new BullQueueWorkers(
52
+ this.redisConnectionOptions,
53
+ singletonServices,
54
+ createWireServices
55
+ )
56
+ }
57
+ return this.queueWorkers
58
+ }
59
+
60
+ /**
61
+ * Get the scheduler service for managing delayed tasks
62
+ */
63
+ getSchedulerService(): BullSchedulerService {
64
+ if (!this.schedulerService) {
65
+ this.schedulerService = new BullSchedulerService(
66
+ this.redisConnectionOptions
67
+ )
68
+ }
69
+ return this.schedulerService
70
+ }
71
+
72
+ /**
73
+ * Close all services
74
+ */
75
+ async close(): Promise<void> {
76
+ const closePromises: Promise<void>[] = []
77
+
78
+ if (this.queueService) {
79
+ // BullQueueService doesn't have close method currently
80
+ }
81
+
82
+ if (this.queueWorkers) {
83
+ closePromises.push(this.queueWorkers.close())
84
+ }
85
+
86
+ if (this.schedulerService) {
87
+ closePromises.push(this.schedulerService.close())
88
+ }
89
+
90
+ await Promise.all(closePromises)
91
+ }
92
+ }
package/src/index.ts CHANGED
@@ -5,8 +5,10 @@
5
5
  * Provides job results, retries, priorities, and most queue features
6
6
  */
7
7
 
8
+ export { BullServiceFactory } from './bull-service-factory.js'
8
9
  export { BullQueueService } from './bull-queue-service.js'
9
10
  export { BullQueueWorkers } from './bull-queue-worker.js'
11
+ export { BullSchedulerService } from './bull-scheduler-service.js'
10
12
 
11
13
  // Re-export core queue types for convenience
12
14
  export type {
@@ -1 +1 @@
1
- {"root":["./src/bull-queue-service.ts","./src/bull-queue-worker.ts","./src/index.ts","./src/utils.ts"],"version":"5.9.3"}
1
+ {"root":["./src/bull-queue-service.ts","./src/bull-queue-worker.ts","./src/bull-scheduler-service.ts","./src/bull-service-factory.ts","./src/index.ts","./src/utils.ts"],"version":"5.9.3"}