@pikku/queue-pg-boss 0.11.2 → 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 +24 -2
- package/dist/pg-boss-queue-service.d.ts +1 -1
- package/dist/pg-boss-queue-worker.d.ts +2 -5
- package/dist/pg-boss-queue-worker.js +8 -15
- package/dist/pg-boss-scheduler-service.d.ts +15 -3
- package/dist/pg-boss-scheduler-service.js +39 -2
- package/dist/pg-boss-service-factory.d.ts +1 -2
- package/dist/pg-boss-service-factory.js +2 -2
- package/dist/utils.d.ts +2 -2
- package/package.json +3 -3
- package/src/pg-boss-queue-service.ts +1 -1
- package/src/pg-boss-queue-worker.test.ts +15 -0
- package/src/pg-boss-queue-worker.ts +10 -19
- package/src/pg-boss-scheduler-service.ts +46 -5
- package/src/pg-boss-service-factory.ts +2 -10
- package/src/utils.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
## 0.12.0
|
|
2
|
+
|
|
3
|
+
## 0.12.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 62a8725: Fix pg-boss queue initialisation: create the queue before registering a worker to avoid a race condition on first startup. Also sanitise scheduler names to meet pg-boss naming constraints.
|
|
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
|
+
|
|
21
|
+
### New Features
|
|
22
|
+
|
|
23
|
+
- `setServices()`, `start()`, `stop()` lifecycle methods on scheduler and queue workers
|
|
24
|
+
|
|
1
25
|
## 0.11.0
|
|
2
26
|
|
|
3
27
|
## 0.11.2
|
|
@@ -8,8 +32,6 @@
|
|
|
8
32
|
- Updated dependencies [db9c7bf]
|
|
9
33
|
- @pikku/core@0.11.2
|
|
10
34
|
|
|
11
|
-
## 0.11.2
|
|
12
|
-
|
|
13
35
|
### Fixes
|
|
14
36
|
|
|
15
37
|
- ddd87eaf: Simplify CreateWireServices type signature for custom Config compatibility
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PgBoss, Request as PgBossRequest } from 'pg-boss';
|
|
1
|
+
import type { PgBoss, Request as PgBossRequest } from 'pg-boss';
|
|
2
2
|
import type { QueueService, QueueJob, JobOptions } from '@pikku/core/queue';
|
|
3
3
|
export declare const mapPikkuJobToPgBoss: (options?: JobOptions) => PgBossRequest["options"];
|
|
4
4
|
/**
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import { PgBoss,
|
|
1
|
+
import type { PgBoss, WorkOptions } from 'pg-boss';
|
|
2
2
|
import type { QueueWorkers, PikkuWorkerConfig, QueueConfigMapping, ConfigValidationResult } from '@pikku/core/queue';
|
|
3
|
-
import { CoreSingletonServices, CreateWireServices } from '@pikku/core';
|
|
4
3
|
export declare const mapPikkuWorkerToPgBoss: (workerConfig?: PikkuWorkerConfig) => WorkOptions;
|
|
5
4
|
/**
|
|
6
5
|
* pg-boss/PostgreSQL queue worker implementation
|
|
7
6
|
* Supports job results, retries, and PostgreSQL-based queuing
|
|
8
7
|
*/
|
|
9
8
|
export declare class PgBossQueueWorkers implements QueueWorkers {
|
|
10
|
-
private singletonServices;
|
|
11
|
-
private createWireServices?;
|
|
12
9
|
readonly name = "pg-boss";
|
|
13
10
|
readonly supportsResults = true;
|
|
14
11
|
/**
|
|
@@ -18,7 +15,7 @@ export declare class PgBossQueueWorkers implements QueueWorkers {
|
|
|
18
15
|
readonly configMappings: QueueConfigMapping;
|
|
19
16
|
private pgBoss;
|
|
20
17
|
private activeWorkers;
|
|
21
|
-
constructor(pgBoss: PgBoss
|
|
18
|
+
constructor(pgBoss: PgBoss);
|
|
22
19
|
/**
|
|
23
20
|
* Scan state and register all compatible processors
|
|
24
21
|
*/
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { registerQueueWorkers, runQueueJob, QueueJobFailedError, QueueJobDiscardedError, } from '@pikku/core/queue';
|
|
2
|
+
import { pikkuState } from '@pikku/core/internal';
|
|
2
3
|
import { mapPgBossJobToQueueJob } from './utils.js';
|
|
3
4
|
export const mapPikkuWorkerToPgBoss = (workerConfig) => {
|
|
4
5
|
const workerOptions = {
|
|
@@ -17,8 +18,6 @@ export const mapPikkuWorkerToPgBoss = (workerConfig) => {
|
|
|
17
18
|
* Supports job results, retries, and PostgreSQL-based queuing
|
|
18
19
|
*/
|
|
19
20
|
export class PgBossQueueWorkers {
|
|
20
|
-
singletonServices;
|
|
21
|
-
createWireServices;
|
|
22
21
|
name = 'pg-boss';
|
|
23
22
|
supportsResults = true;
|
|
24
23
|
/**
|
|
@@ -85,34 +84,28 @@ export class PgBossQueueWorkers {
|
|
|
85
84
|
};
|
|
86
85
|
pgBoss;
|
|
87
86
|
activeWorkers = new Map();
|
|
88
|
-
constructor(pgBoss
|
|
89
|
-
this.singletonServices = singletonServices;
|
|
90
|
-
this.createWireServices = createWireServices;
|
|
87
|
+
constructor(pgBoss) {
|
|
91
88
|
this.pgBoss = pgBoss;
|
|
92
89
|
}
|
|
93
90
|
/**
|
|
94
91
|
* Scan state and register all compatible processors
|
|
95
92
|
*/
|
|
96
93
|
async registerQueues() {
|
|
97
|
-
|
|
94
|
+
const logger = pikkuState(null, 'package', 'singletonServices').logger;
|
|
95
|
+
return await registerQueueWorkers(this.configMappings, logger, async (queueName, processor) => {
|
|
98
96
|
await this.pgBoss.createQueue(queueName);
|
|
99
|
-
const workerId = await this.pgBoss.work(processor.
|
|
97
|
+
const workerId = await this.pgBoss.work(processor.name, {
|
|
100
98
|
...mapPikkuWorkerToPgBoss(processor.config),
|
|
101
99
|
includeMetadata: true,
|
|
102
100
|
}, async (jobs) => {
|
|
103
|
-
if (!this.singletonServices) {
|
|
104
|
-
throw new Error('Singleton services not available');
|
|
105
|
-
}
|
|
106
101
|
if (!jobs || jobs.length === 0) {
|
|
107
|
-
|
|
102
|
+
logger.warn(`No jobs received for queue ${queueName}`);
|
|
108
103
|
return;
|
|
109
104
|
}
|
|
110
105
|
// Process all jobs in parallel
|
|
111
106
|
await Promise.all(jobs.map(async (job) => {
|
|
112
107
|
try {
|
|
113
108
|
await runQueueJob({
|
|
114
|
-
singletonServices: this.singletonServices,
|
|
115
|
-
createWireServices: this.createWireServices,
|
|
116
109
|
job: mapPgBossJobToQueueJob(job, this.pgBoss),
|
|
117
110
|
});
|
|
118
111
|
}
|
|
@@ -125,7 +118,7 @@ export class PgBossQueueWorkers {
|
|
|
125
118
|
}
|
|
126
119
|
else if (error instanceof QueueJobDiscardedError) {
|
|
127
120
|
// For pg-boss, complete the job successfully to discard it
|
|
128
|
-
|
|
121
|
+
logger.info(`PgBoss job ${job.id} discarded: ${error.message}`);
|
|
129
122
|
await this.pgBoss.complete(queueName, job.id);
|
|
130
123
|
}
|
|
131
124
|
else {
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { PgBoss } from 'pg-boss';
|
|
2
|
-
import {
|
|
1
|
+
import type { PgBoss } from 'pg-boss';
|
|
2
|
+
import type { ScheduledTaskInfo, ScheduledTaskSummary, CoreUserSession } from '@pikku/core';
|
|
3
|
+
import { SchedulerService } from '@pikku/core';
|
|
3
4
|
/**
|
|
4
5
|
* pg-boss scheduler service implementation
|
|
5
|
-
* Uses pg-boss's schedule() API to store recurring jobs in PostgreSQL
|
|
6
|
+
* Uses pg-boss's schedule() API to store recurring jobs in PostgreSQL.
|
|
7
|
+
* Handles both one-off delayed RPCs and recurring cron-scheduled tasks.
|
|
6
8
|
*/
|
|
7
9
|
export declare class PgBossSchedulerService extends SchedulerService {
|
|
8
10
|
private pgBoss;
|
|
11
|
+
private scheduledCronNames;
|
|
9
12
|
constructor(pgBoss: PgBoss);
|
|
10
13
|
/**
|
|
11
14
|
* Initialize - no-op as pg-boss is already initialized by factory
|
|
@@ -32,4 +35,13 @@ export declare class PgBossSchedulerService extends SchedulerService {
|
|
|
32
35
|
* Close - no-op as pg-boss lifecycle is managed by factory
|
|
33
36
|
*/
|
|
34
37
|
close(): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Start recurring scheduled tasks.
|
|
40
|
+
* Registers a pg-boss worker to process recurring jobs via runScheduledTask.
|
|
41
|
+
*/
|
|
42
|
+
start(): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Stop recurring scheduled tasks by unscheduling them from pg-boss.
|
|
45
|
+
*/
|
|
46
|
+
stop(): Promise<void>;
|
|
35
47
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { SchedulerService, parseDurationString
|
|
1
|
+
import { SchedulerService, parseDurationString } from '@pikku/core';
|
|
2
|
+
import { pikkuState } from '@pikku/core/internal';
|
|
3
|
+
import { runScheduledTask, getScheduledTasks } from '@pikku/core/scheduler';
|
|
2
4
|
/**
|
|
3
5
|
* pg-boss scheduler service implementation
|
|
4
|
-
* Uses pg-boss's schedule() API to store recurring jobs in PostgreSQL
|
|
6
|
+
* Uses pg-boss's schedule() API to store recurring jobs in PostgreSQL.
|
|
7
|
+
* Handles both one-off delayed RPCs and recurring cron-scheduled tasks.
|
|
5
8
|
*/
|
|
6
9
|
export class PgBossSchedulerService extends SchedulerService {
|
|
7
10
|
pgBoss;
|
|
11
|
+
scheduledCronNames = [];
|
|
8
12
|
constructor(pgBoss) {
|
|
9
13
|
super();
|
|
10
14
|
this.pgBoss = pgBoss;
|
|
@@ -77,4 +81,37 @@ export class PgBossSchedulerService extends SchedulerService {
|
|
|
77
81
|
async close() {
|
|
78
82
|
// No-op - pg-boss lifecycle is managed by factory
|
|
79
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Start recurring scheduled tasks.
|
|
86
|
+
* Registers a pg-boss worker to process recurring jobs via runScheduledTask.
|
|
87
|
+
*/
|
|
88
|
+
async start() {
|
|
89
|
+
const logger = pikkuState(null, 'package', 'singletonServices').logger;
|
|
90
|
+
const scheduledTasks = getScheduledTasks();
|
|
91
|
+
for (const [name, task] of scheduledTasks) {
|
|
92
|
+
const cronName = `pikku-recurring-scheduled-task_${name.replace(/[^a-zA-Z0-9_\-.]/g, '_')}`;
|
|
93
|
+
await this.pgBoss.createQueue(cronName);
|
|
94
|
+
await this.pgBoss.schedule(cronName, task.schedule, {
|
|
95
|
+
rpcName: name,
|
|
96
|
+
});
|
|
97
|
+
this.scheduledCronNames.push(cronName);
|
|
98
|
+
// Register a worker to process the scheduled jobs
|
|
99
|
+
await this.pgBoss.work(cronName, async (jobs) => {
|
|
100
|
+
for (const job of jobs) {
|
|
101
|
+
const { rpcName } = job.data;
|
|
102
|
+
logger.info(`Running scheduled task: ${rpcName}`);
|
|
103
|
+
await runScheduledTask({ name: rpcName });
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Stop recurring scheduled tasks by unscheduling them from pg-boss.
|
|
110
|
+
*/
|
|
111
|
+
async stop() {
|
|
112
|
+
for (const cronName of this.scheduledCronNames) {
|
|
113
|
+
await this.pgBoss.unschedule(cronName);
|
|
114
|
+
}
|
|
115
|
+
this.scheduledCronNames = [];
|
|
116
|
+
}
|
|
80
117
|
}
|
|
@@ -2,7 +2,6 @@ import { PgBoss, type ConstructorOptions } from 'pg-boss';
|
|
|
2
2
|
import { PgBossQueueService } from './pg-boss-queue-service.js';
|
|
3
3
|
import { PgBossQueueWorkers } from './pg-boss-queue-worker.js';
|
|
4
4
|
import { PgBossSchedulerService } from './pg-boss-scheduler-service.js';
|
|
5
|
-
import type { CoreSingletonServices, CreateWireServices } from '@pikku/core';
|
|
6
5
|
/**
|
|
7
6
|
* Factory class for pg-boss services
|
|
8
7
|
* Manages a single PgBoss instance shared across queue, worker, and scheduler services
|
|
@@ -25,7 +24,7 @@ export declare class PgBossServiceFactory {
|
|
|
25
24
|
/**
|
|
26
25
|
* Get the queue workers for processing jobs
|
|
27
26
|
*/
|
|
28
|
-
getQueueWorkers(
|
|
27
|
+
getQueueWorkers(): PgBossQueueWorkers;
|
|
29
28
|
/**
|
|
30
29
|
* Get the scheduler service for managing recurring tasks
|
|
31
30
|
*/
|
|
@@ -44,9 +44,9 @@ export class PgBossServiceFactory {
|
|
|
44
44
|
/**
|
|
45
45
|
* Get the queue workers for processing jobs
|
|
46
46
|
*/
|
|
47
|
-
getQueueWorkers(
|
|
47
|
+
getQueueWorkers() {
|
|
48
48
|
if (!this.queueWorkers) {
|
|
49
|
-
this.queueWorkers = new PgBossQueueWorkers(this.pgBoss
|
|
49
|
+
this.queueWorkers = new PgBossQueueWorkers(this.pgBoss);
|
|
50
50
|
}
|
|
51
51
|
return this.queueWorkers;
|
|
52
52
|
}
|
package/dist/utils.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/queue-pg-boss",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.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.12.1"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"pg-boss": "^12.
|
|
19
|
+
"pg-boss": "^12.9.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"typescript": "^5.9"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { describe, test } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
|
|
4
|
+
import { PgBossQueueWorkers } from './pg-boss-queue-worker.js'
|
|
5
|
+
|
|
6
|
+
describe('PgBossQueueWorkers', () => {
|
|
7
|
+
test('requires setJobRunner before registerQueues', async () => {
|
|
8
|
+
const workers = new PgBossQueueWorkers({} as any)
|
|
9
|
+
|
|
10
|
+
await assert.rejects(() => workers.registerQueues(), {
|
|
11
|
+
message:
|
|
12
|
+
'PgBossQueueWorkers requires setJobRunner() before registerQueues()',
|
|
13
|
+
})
|
|
14
|
+
})
|
|
15
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PgBoss,
|
|
1
|
+
import type { PgBoss, WorkOptions } from 'pg-boss'
|
|
2
2
|
import type {
|
|
3
3
|
QueueWorkers,
|
|
4
4
|
PikkuWorkerConfig,
|
|
@@ -6,12 +6,12 @@ import type {
|
|
|
6
6
|
ConfigValidationResult,
|
|
7
7
|
} from '@pikku/core/queue'
|
|
8
8
|
import {
|
|
9
|
-
runQueueJob,
|
|
10
9
|
registerQueueWorkers,
|
|
10
|
+
runQueueJob,
|
|
11
11
|
QueueJobFailedError,
|
|
12
12
|
QueueJobDiscardedError,
|
|
13
13
|
} from '@pikku/core/queue'
|
|
14
|
-
import {
|
|
14
|
+
import { pikkuState } from '@pikku/core/internal'
|
|
15
15
|
import { mapPgBossJobToQueueJob } from './utils.js'
|
|
16
16
|
|
|
17
17
|
export const mapPikkuWorkerToPgBoss = (
|
|
@@ -121,11 +121,7 @@ export class PgBossQueueWorkers implements QueueWorkers {
|
|
|
121
121
|
private pgBoss: PgBoss
|
|
122
122
|
private activeWorkers = new Map<string, string>()
|
|
123
123
|
|
|
124
|
-
constructor(
|
|
125
|
-
pgBoss: PgBoss,
|
|
126
|
-
private singletonServices: CoreSingletonServices,
|
|
127
|
-
private createWireServices?: CreateWireServices
|
|
128
|
-
) {
|
|
124
|
+
constructor(pgBoss: PgBoss) {
|
|
129
125
|
this.pgBoss = pgBoss
|
|
130
126
|
}
|
|
131
127
|
|
|
@@ -133,25 +129,22 @@ export class PgBossQueueWorkers implements QueueWorkers {
|
|
|
133
129
|
* Scan state and register all compatible processors
|
|
134
130
|
*/
|
|
135
131
|
async registerQueues(): Promise<Record<string, ConfigValidationResult[]>> {
|
|
132
|
+
const logger = pikkuState(null, 'package', 'singletonServices')!.logger
|
|
133
|
+
|
|
136
134
|
return await registerQueueWorkers(
|
|
137
135
|
this.configMappings,
|
|
138
|
-
|
|
136
|
+
logger,
|
|
139
137
|
async (queueName, processor) => {
|
|
140
138
|
await this.pgBoss.createQueue(queueName)
|
|
141
139
|
const workerId = await this.pgBoss.work<any>(
|
|
142
|
-
processor.
|
|
140
|
+
processor.name,
|
|
143
141
|
{
|
|
144
142
|
...mapPikkuWorkerToPgBoss(processor.config),
|
|
145
143
|
includeMetadata: true,
|
|
146
144
|
},
|
|
147
145
|
async (jobs) => {
|
|
148
|
-
if (!this.singletonServices) {
|
|
149
|
-
throw new Error('Singleton services not available')
|
|
150
|
-
}
|
|
151
146
|
if (!jobs || jobs.length === 0) {
|
|
152
|
-
|
|
153
|
-
`No jobs received for queue ${queueName}`
|
|
154
|
-
)
|
|
147
|
+
logger.warn(`No jobs received for queue ${queueName}`)
|
|
155
148
|
return
|
|
156
149
|
}
|
|
157
150
|
// Process all jobs in parallel
|
|
@@ -159,8 +152,6 @@ export class PgBossQueueWorkers implements QueueWorkers {
|
|
|
159
152
|
jobs.map(async (job) => {
|
|
160
153
|
try {
|
|
161
154
|
await runQueueJob({
|
|
162
|
-
singletonServices: this.singletonServices,
|
|
163
|
-
createWireServices: this.createWireServices,
|
|
164
155
|
job: mapPgBossJobToQueueJob(job, this.pgBoss),
|
|
165
156
|
})
|
|
166
157
|
} catch (error: unknown) {
|
|
@@ -171,7 +162,7 @@ export class PgBossQueueWorkers implements QueueWorkers {
|
|
|
171
162
|
})
|
|
172
163
|
} else if (error instanceof QueueJobDiscardedError) {
|
|
173
164
|
// For pg-boss, complete the job successfully to discard it
|
|
174
|
-
|
|
165
|
+
logger.info(
|
|
175
166
|
`PgBoss job ${job.id} discarded: ${error.message}`
|
|
176
167
|
)
|
|
177
168
|
await this.pgBoss.complete(queueName, job.id)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { PgBoss } from 'pg-boss'
|
|
2
|
-
import {
|
|
3
|
-
SchedulerService,
|
|
1
|
+
import type { PgBoss } from 'pg-boss'
|
|
2
|
+
import type {
|
|
4
3
|
ScheduledTaskInfo,
|
|
5
4
|
ScheduledTaskSummary,
|
|
6
5
|
CoreUserSession,
|
|
7
|
-
parseDurationString,
|
|
8
6
|
} from '@pikku/core'
|
|
7
|
+
import { SchedulerService, parseDurationString } from '@pikku/core'
|
|
8
|
+
import { pikkuState } from '@pikku/core/internal'
|
|
9
|
+
import { runScheduledTask, getScheduledTasks } from '@pikku/core/scheduler'
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Data stored in scheduled job
|
|
@@ -18,9 +19,12 @@ interface ScheduledJobData {
|
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* pg-boss scheduler service implementation
|
|
21
|
-
* Uses pg-boss's schedule() API to store recurring jobs in PostgreSQL
|
|
22
|
+
* Uses pg-boss's schedule() API to store recurring jobs in PostgreSQL.
|
|
23
|
+
* Handles both one-off delayed RPCs and recurring cron-scheduled tasks.
|
|
22
24
|
*/
|
|
23
25
|
export class PgBossSchedulerService extends SchedulerService {
|
|
26
|
+
private scheduledCronNames: string[] = []
|
|
27
|
+
|
|
24
28
|
constructor(private pgBoss: PgBoss) {
|
|
25
29
|
super()
|
|
26
30
|
}
|
|
@@ -118,4 +122,41 @@ export class PgBossSchedulerService extends SchedulerService {
|
|
|
118
122
|
async close(): Promise<void> {
|
|
119
123
|
// No-op - pg-boss lifecycle is managed by factory
|
|
120
124
|
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Start recurring scheduled tasks.
|
|
128
|
+
* Registers a pg-boss worker to process recurring jobs via runScheduledTask.
|
|
129
|
+
*/
|
|
130
|
+
async start(): Promise<void> {
|
|
131
|
+
const logger = pikkuState(null, 'package', 'singletonServices')!.logger
|
|
132
|
+
const scheduledTasks = getScheduledTasks()
|
|
133
|
+
|
|
134
|
+
for (const [name, task] of scheduledTasks) {
|
|
135
|
+
const cronName = `pikku-recurring-scheduled-task_${name.replace(/[^a-zA-Z0-9_\-.]/g, '_')}`
|
|
136
|
+
await this.pgBoss.createQueue(cronName)
|
|
137
|
+
await this.pgBoss.schedule(cronName, task.schedule, {
|
|
138
|
+
rpcName: name,
|
|
139
|
+
} as ScheduledJobData)
|
|
140
|
+
this.scheduledCronNames.push(cronName)
|
|
141
|
+
|
|
142
|
+
// Register a worker to process the scheduled jobs
|
|
143
|
+
await this.pgBoss.work<ScheduledJobData>(cronName, async (jobs) => {
|
|
144
|
+
for (const job of jobs) {
|
|
145
|
+
const { rpcName } = job.data
|
|
146
|
+
logger.info(`Running scheduled task: ${rpcName}`)
|
|
147
|
+
await runScheduledTask({ name: rpcName })
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Stop recurring scheduled tasks by unscheduling them from pg-boss.
|
|
155
|
+
*/
|
|
156
|
+
async stop(): Promise<void> {
|
|
157
|
+
for (const cronName of this.scheduledCronNames) {
|
|
158
|
+
await this.pgBoss.unschedule(cronName)
|
|
159
|
+
}
|
|
160
|
+
this.scheduledCronNames = []
|
|
161
|
+
}
|
|
121
162
|
}
|
|
@@ -2,7 +2,6 @@ import { PgBoss, type ConstructorOptions } from 'pg-boss'
|
|
|
2
2
|
import { PgBossQueueService } from './pg-boss-queue-service.js'
|
|
3
3
|
import { PgBossQueueWorkers } from './pg-boss-queue-worker.js'
|
|
4
4
|
import { PgBossSchedulerService } from './pg-boss-scheduler-service.js'
|
|
5
|
-
import type { CoreSingletonServices, CreateWireServices } from '@pikku/core'
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Factory class for pg-boss services
|
|
@@ -50,16 +49,9 @@ export class PgBossServiceFactory {
|
|
|
50
49
|
/**
|
|
51
50
|
* Get the queue workers for processing jobs
|
|
52
51
|
*/
|
|
53
|
-
getQueueWorkers(
|
|
54
|
-
singletonServices: CoreSingletonServices,
|
|
55
|
-
createWireServices?: CreateWireServices
|
|
56
|
-
): PgBossQueueWorkers {
|
|
52
|
+
getQueueWorkers(): PgBossQueueWorkers {
|
|
57
53
|
if (!this.queueWorkers) {
|
|
58
|
-
this.queueWorkers = new PgBossQueueWorkers(
|
|
59
|
-
this.pgBoss,
|
|
60
|
-
singletonServices,
|
|
61
|
-
createWireServices
|
|
62
|
-
)
|
|
54
|
+
this.queueWorkers = new PgBossQueueWorkers(this.pgBoss)
|
|
63
55
|
}
|
|
64
56
|
return this.queueWorkers
|
|
65
57
|
}
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { QueueJob, QueueJobStatus } from '@pikku/core/queue'
|
|
2
|
-
import { PgBoss,
|
|
1
|
+
import type { QueueJob, QueueJobStatus } from '@pikku/core/queue'
|
|
2
|
+
import type { PgBoss, JobWithMetadata } from 'pg-boss'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Map pg-boss job state to our queue job status
|