@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 +21 -0
- package/dist/bull-queue-worker.d.ts +3 -3
- package/dist/bull-queue-worker.js +4 -4
- package/dist/bull-scheduler-service.d.ts +35 -0
- package/dist/bull-scheduler-service.js +100 -0
- package/dist/bull-service-factory.d.ts +36 -0
- package/dist/bull-service-factory.js +65 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/package.json +3 -3
- package/src/bull-queue-worker.ts +4 -4
- package/src/bull-scheduler-service.ts +139 -0
- package/src/bull-service-factory.ts +92 -0
- package/src/index.ts +2 -0
- package/tsconfig.tsbuildinfo +1 -1
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,
|
|
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
|
|
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,
|
|
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
|
-
|
|
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,
|
|
104
|
+
constructor(redisConnectionOptions, singletonServices, createWireServices) {
|
|
105
105
|
this.redisConnectionOptions = redisConnectionOptions;
|
|
106
106
|
this.singletonServices = singletonServices;
|
|
107
|
-
this.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
16
|
+
"@pikku/core": "^0.11.1"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"bullmq": "^5.
|
|
19
|
+
"bullmq": "^5.63.2",
|
|
20
20
|
"ioredis": "^5.8.2"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
package/src/bull-queue-worker.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
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 {
|
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -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"}
|