@rvoh/psychic-workers 0.3.2 → 0.4.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/dist/cjs/src/background/BaseBackgroundedModel.js +7 -4
- package/dist/cjs/src/background/BaseBackgroundedService.js +4 -2
- package/dist/cjs/src/background/index.js +26 -13
- package/dist/cjs/src/helpers/durationToSeconds.js +9 -0
- package/dist/esm/src/background/BaseBackgroundedModel.js +7 -4
- package/dist/esm/src/background/BaseBackgroundedService.js +4 -2
- package/dist/esm/src/background/index.js +26 -13
- package/dist/esm/src/helpers/durationToSeconds.js +6 -0
- package/dist/types/src/background/BaseBackgroundedModel.d.ts +3 -3
- package/dist/types/src/background/BaseBackgroundedService.d.ts +2 -2
- package/dist/types/src/background/index.d.ts +6 -3
- package/dist/types/src/helpers/EnvInternal.d.ts +2 -2
- package/dist/types/src/helpers/durationToSeconds.d.ts +2 -0
- package/dist/types/src/types/background.d.ts +14 -0
- package/package.json +2 -2
@@ -2,6 +2,7 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
const dream_1 = require("@rvoh/dream");
|
4
4
|
const index_js_1 = require("./index.js");
|
5
|
+
const durationToSeconds_js_1 = require("../helpers/durationToSeconds.js");
|
5
6
|
class BaseBackgroundedModel extends dream_1.Dream {
|
6
7
|
/**
|
7
8
|
* A getter meant to be overridden in child classes. This does
|
@@ -76,11 +77,12 @@ class BaseBackgroundedModel extends dream_1.Dream {
|
|
76
77
|
* @param methodName - the name of the static method you wish to run in the background
|
77
78
|
* @param args - a variadic list of arguments to be sent to your method
|
78
79
|
*/
|
79
|
-
static async backgroundWithDelay(
|
80
|
+
static async backgroundWithDelay(delay, methodName, ...args) {
|
80
81
|
const safeThis = this;
|
81
82
|
return await index_js_1.default.staticMethod(safeThis, methodName, {
|
82
83
|
globalName: safeThis.globalName,
|
83
|
-
delaySeconds,
|
84
|
+
delaySeconds: (0, durationToSeconds_js_1.default)(delay),
|
85
|
+
jobId: delay.jobId,
|
84
86
|
args,
|
85
87
|
jobConfig: safeThis.backgroundJobConfig,
|
86
88
|
});
|
@@ -143,11 +145,12 @@ class BaseBackgroundedModel extends dream_1.Dream {
|
|
143
145
|
* @param methodName - the name of the static method you wish to run in the background
|
144
146
|
* @param args - a variadic list of arguments to be sent to your method
|
145
147
|
*/
|
146
|
-
async backgroundWithDelay(
|
148
|
+
async backgroundWithDelay(delay, methodName, ...args) {
|
147
149
|
const safeThis = this;
|
148
150
|
return await index_js_1.default.modelInstanceMethod(safeThis, methodName, {
|
149
151
|
args,
|
150
|
-
delaySeconds,
|
152
|
+
delaySeconds: (0, durationToSeconds_js_1.default)(delay),
|
153
|
+
jobId: delay.jobId,
|
151
154
|
jobConfig: safeThis.backgroundJobConfig,
|
152
155
|
});
|
153
156
|
}
|
@@ -2,6 +2,7 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
const dream_1 = require("@rvoh/dream");
|
4
4
|
const index_js_1 = require("./index.js");
|
5
|
+
const durationToSeconds_js_1 = require("../helpers/durationToSeconds.js");
|
5
6
|
class BaseBackgroundedService {
|
6
7
|
/**
|
7
8
|
* A getter meant to be overridden in child classes. This does
|
@@ -88,11 +89,12 @@ class BaseBackgroundedService {
|
|
88
89
|
* @param methodName - the name of the static method you wish to run in the background
|
89
90
|
* @param args - a variadic list of arguments to be sent to your method
|
90
91
|
*/
|
91
|
-
static async backgroundWithDelay(
|
92
|
+
static async backgroundWithDelay(delay, methodName, ...args) {
|
92
93
|
const safeThis = this;
|
93
94
|
return await index_js_1.default.staticMethod(safeThis, methodName, {
|
94
95
|
globalName: safeThis.globalName,
|
95
|
-
delaySeconds,
|
96
|
+
delaySeconds: (0, durationToSeconds_js_1.default)(delay),
|
97
|
+
jobId: delay.jobId,
|
96
98
|
args,
|
97
99
|
jobConfig: safeThis.backgroundJobConfig,
|
98
100
|
});
|
@@ -14,6 +14,7 @@ const NoQueueForSpecifiedWorkstream_js_1 = require("../error/background/NoQueueF
|
|
14
14
|
const EnvInternal_js_1 = require("../helpers/EnvInternal.js");
|
15
15
|
const index_js_1 = require("../psychic-app-workers/index.js");
|
16
16
|
const nameToRedisQueueName_js_1 = require("./helpers/nameToRedisQueueName.js");
|
17
|
+
const DEFAULT_CONCURRENCY = 10;
|
17
18
|
/**
|
18
19
|
* the underlying class driving the `background` singleton,
|
19
20
|
* available as an import from `psychic-workers`.
|
@@ -130,13 +131,15 @@ class Background {
|
|
130
131
|
}
|
131
132
|
async shutdownAndExit() {
|
132
133
|
await this.shutdown();
|
133
|
-
|
134
|
+
// https://docs.bullmq.io/guide/going-to-production#gracefully-shut-down-workers
|
135
|
+
process.exit(0);
|
134
136
|
}
|
135
137
|
/**
|
136
138
|
* Shuts down workers, closes all redis connections
|
137
139
|
*/
|
138
140
|
async shutdown() {
|
139
|
-
|
141
|
+
if (!EnvInternal_js_1.default.isTest)
|
142
|
+
psychic_1.PsychicApp.log(`[psychic-workers] shutdown`);
|
140
143
|
const psychicWorkersApp = index_js_1.default.getOrFail();
|
141
144
|
for (const hook of psychicWorkersApp.hooks.workerShutdown) {
|
142
145
|
await hook();
|
@@ -148,18 +151,18 @@ class Background {
|
|
148
151
|
* closes all redis connections for workers and queues
|
149
152
|
*/
|
150
153
|
async closeAllRedisConnections() {
|
151
|
-
|
152
|
-
|
153
|
-
}
|
154
|
+
if (!EnvInternal_js_1.default.isTest)
|
155
|
+
psychic_1.PsychicApp.log(`[psychic-workers] closeAllRedisConnections`);
|
154
156
|
for (const worker of this.workers) {
|
155
157
|
await worker.close();
|
156
158
|
}
|
157
159
|
for (const connection of this.redisConnections) {
|
158
160
|
try {
|
159
|
-
connection.
|
161
|
+
await connection.quit();
|
160
162
|
}
|
161
|
-
catch {
|
162
|
-
|
163
|
+
catch (error) {
|
164
|
+
if (!EnvInternal_js_1.default.isTest)
|
165
|
+
psychic_1.PsychicApp.logWithLevel('error', `[psychic-workers] error quitting Redis:`, error);
|
163
166
|
}
|
164
167
|
}
|
165
168
|
}
|
@@ -205,7 +208,7 @@ class Background {
|
|
205
208
|
for (let i = 0; i < workerCount; i++) {
|
206
209
|
this._workers.push(new Background.Worker(formattedQueueName, async (job) => await this.doWork(job), {
|
207
210
|
connection: defaultWorkerConnection,
|
208
|
-
concurrency: backgroundOptions.defaultWorkstream?.concurrency ||
|
211
|
+
concurrency: backgroundOptions.defaultWorkstream?.concurrency || DEFAULT_CONCURRENCY,
|
209
212
|
}));
|
210
213
|
}
|
211
214
|
}
|
@@ -252,7 +255,7 @@ class Background {
|
|
252
255
|
limit: namedWorkstream.rateLimit,
|
253
256
|
},
|
254
257
|
connection: namedWorkstreamWorkerConnection,
|
255
|
-
concurrency: namedWorkstream.concurrency ||
|
258
|
+
concurrency: namedWorkstream.concurrency || DEFAULT_CONCURRENCY,
|
256
259
|
// explicitly typing as WorkerOptions because Psychic can't be aware of BullMQ Pro options
|
257
260
|
}));
|
258
261
|
}
|
@@ -371,11 +374,15 @@ class Background {
|
|
371
374
|
work() {
|
372
375
|
this.connect({ activateWorkers: true });
|
373
376
|
process.on('SIGTERM', () => {
|
377
|
+
if (!EnvInternal_js_1.default.isTest)
|
378
|
+
psychic_1.PsychicApp.log('[psychic-workers] handle SIGTERM');
|
374
379
|
void this.shutdownAndExit()
|
375
380
|
.then(() => { })
|
376
381
|
.catch(() => { });
|
377
382
|
});
|
378
383
|
process.on('SIGINT', () => {
|
384
|
+
if (!EnvInternal_js_1.default.isTest)
|
385
|
+
psychic_1.PsychicApp.log('[psychic-workers] handle SIGINT');
|
379
386
|
void this.shutdownAndExit()
|
380
387
|
.then(() => { })
|
381
388
|
.catch(() => { });
|
@@ -392,7 +399,7 @@ class Background {
|
|
392
399
|
* @param importKey - (optional) the import key for the class
|
393
400
|
* @param jobConfig - (optional) the background job config to use when backgrounding this method
|
394
401
|
*/
|
395
|
-
async staticMethod(ObjectClass, method, { globalName, delaySeconds, args = [], jobConfig = {}, }) {
|
402
|
+
async staticMethod(ObjectClass, method, { globalName, delaySeconds, jobId, args = [], jobConfig = {}, }) {
|
396
403
|
this.connect();
|
397
404
|
await this._addToQueue(`BackgroundJobQueueStaticJob`, {
|
398
405
|
globalName,
|
@@ -400,6 +407,7 @@ class Background {
|
|
400
407
|
args,
|
401
408
|
}, {
|
402
409
|
delaySeconds,
|
410
|
+
jobId,
|
403
411
|
jobConfig,
|
404
412
|
groupId: this.jobConfigToGroupId(jobConfig),
|
405
413
|
priority: this.jobConfigToPriority(jobConfig),
|
@@ -472,7 +480,7 @@ class Background {
|
|
472
480
|
* @param importKey - (optional) the import key for the class
|
473
481
|
* @param jobConfig - (optional) the background job config to use when backgrounding this method
|
474
482
|
*/
|
475
|
-
async modelInstanceMethod(modelInstance, method, { delaySeconds, args = [], jobConfig = {}, }) {
|
483
|
+
async modelInstanceMethod(modelInstance, method, { delaySeconds, jobId, args = [], jobConfig = {}, }) {
|
476
484
|
this.connect();
|
477
485
|
await this._addToQueue('BackgroundJobQueueModelInstanceJob', {
|
478
486
|
id: modelInstance.primaryKeyValue,
|
@@ -481,16 +489,19 @@ class Background {
|
|
481
489
|
args,
|
482
490
|
}, {
|
483
491
|
delaySeconds,
|
492
|
+
jobId,
|
484
493
|
jobConfig,
|
485
494
|
groupId: this.jobConfigToGroupId(jobConfig),
|
486
495
|
priority: this.jobConfigToPriority(jobConfig),
|
487
496
|
});
|
488
497
|
}
|
489
498
|
// should be private, but public so we can test
|
490
|
-
async _addToQueue(jobType, jobData, { delaySeconds, jobConfig, priority, groupId, }) {
|
499
|
+
async _addToQueue(jobType, jobData, { delaySeconds, jobId, jobConfig, priority, groupId, }) {
|
491
500
|
// set this variable out side of the conditional so that
|
492
501
|
// mismatches will raise exceptions even in tests
|
493
502
|
const queueInstance = this.queueInstance(jobConfig);
|
503
|
+
// if delaySeconds is 0, we will intentionally treat
|
504
|
+
// this as `undefined`
|
494
505
|
const delay = delaySeconds ? delaySeconds * 1000 : undefined;
|
495
506
|
if (EnvInternal_js_1.default.isTest && !EnvInternal_js_1.default.boolean('REALLY_TEST_BACKGROUND_QUEUE')) {
|
496
507
|
const queue = new Background.Queue('TestQueue', { connection: {} });
|
@@ -504,6 +515,7 @@ class Background {
|
|
504
515
|
if (groupId && priority) {
|
505
516
|
await queueInstance.add(jobType, jobData, {
|
506
517
|
delay,
|
518
|
+
jobId,
|
507
519
|
group: {
|
508
520
|
...this.groupIdToGroupConfig(groupId),
|
509
521
|
priority: this.mapPriorityWordToPriorityNumber(priority),
|
@@ -515,6 +527,7 @@ class Background {
|
|
515
527
|
else {
|
516
528
|
await queueInstance.add(jobType, jobData, {
|
517
529
|
delay,
|
530
|
+
jobId,
|
518
531
|
group: this.groupIdToGroupConfig(groupId),
|
519
532
|
priority: this.mapPriorityWordToPriorityNumber(priority),
|
520
533
|
// explicitly typing as JobsOptions because Psychic can't be aware of BullMQ Pro options
|
@@ -0,0 +1,9 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.default = durationToSeconds;
|
4
|
+
function durationToSeconds(duration) {
|
5
|
+
return ((duration.seconds ? duration.seconds : 0) +
|
6
|
+
(duration.minutes ? duration.minutes * 60 : 0) +
|
7
|
+
(duration.hours ? duration.hours * 60 * 60 : 0) +
|
8
|
+
(duration.days ? duration.days * 60 * 60 * 24 : 0));
|
9
|
+
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { Dream } from '@rvoh/dream';
|
2
2
|
import background from './index.js';
|
3
|
+
import durationToSeconds from '../helpers/durationToSeconds.js';
|
3
4
|
export default class BaseBackgroundedModel extends Dream {
|
4
5
|
/**
|
5
6
|
* A getter meant to be overridden in child classes. This does
|
@@ -74,11 +75,12 @@ export default class BaseBackgroundedModel extends Dream {
|
|
74
75
|
* @param methodName - the name of the static method you wish to run in the background
|
75
76
|
* @param args - a variadic list of arguments to be sent to your method
|
76
77
|
*/
|
77
|
-
static async backgroundWithDelay(
|
78
|
+
static async backgroundWithDelay(delay, methodName, ...args) {
|
78
79
|
const safeThis = this;
|
79
80
|
return await background.staticMethod(safeThis, methodName, {
|
80
81
|
globalName: safeThis.globalName,
|
81
|
-
delaySeconds,
|
82
|
+
delaySeconds: durationToSeconds(delay),
|
83
|
+
jobId: delay.jobId,
|
82
84
|
args,
|
83
85
|
jobConfig: safeThis.backgroundJobConfig,
|
84
86
|
});
|
@@ -141,11 +143,12 @@ export default class BaseBackgroundedModel extends Dream {
|
|
141
143
|
* @param methodName - the name of the static method you wish to run in the background
|
142
144
|
* @param args - a variadic list of arguments to be sent to your method
|
143
145
|
*/
|
144
|
-
async backgroundWithDelay(
|
146
|
+
async backgroundWithDelay(delay, methodName, ...args) {
|
145
147
|
const safeThis = this;
|
146
148
|
return await background.modelInstanceMethod(safeThis, methodName, {
|
147
149
|
args,
|
148
|
-
delaySeconds,
|
150
|
+
delaySeconds: durationToSeconds(delay),
|
151
|
+
jobId: delay.jobId,
|
149
152
|
jobConfig: safeThis.backgroundJobConfig,
|
150
153
|
});
|
151
154
|
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { GlobalNameNotSet } from '@rvoh/dream';
|
2
2
|
import background from './index.js';
|
3
|
+
import durationToSeconds from '../helpers/durationToSeconds.js';
|
3
4
|
export default class BaseBackgroundedService {
|
4
5
|
/**
|
5
6
|
* A getter meant to be overridden in child classes. This does
|
@@ -86,11 +87,12 @@ export default class BaseBackgroundedService {
|
|
86
87
|
* @param methodName - the name of the static method you wish to run in the background
|
87
88
|
* @param args - a variadic list of arguments to be sent to your method
|
88
89
|
*/
|
89
|
-
static async backgroundWithDelay(
|
90
|
+
static async backgroundWithDelay(delay, methodName, ...args) {
|
90
91
|
const safeThis = this;
|
91
92
|
return await background.staticMethod(safeThis, methodName, {
|
92
93
|
globalName: safeThis.globalName,
|
93
|
-
delaySeconds,
|
94
|
+
delaySeconds: durationToSeconds(delay),
|
95
|
+
jobId: delay.jobId,
|
94
96
|
args,
|
95
97
|
jobConfig: safeThis.backgroundJobConfig,
|
96
98
|
});
|
@@ -10,6 +10,7 @@ import NoQueueForSpecifiedWorkstream from '../error/background/NoQueueForSpecifi
|
|
10
10
|
import EnvInternal from '../helpers/EnvInternal.js';
|
11
11
|
import PsychicAppWorkers from '../psychic-app-workers/index.js';
|
12
12
|
import nameToRedisQueueName from './helpers/nameToRedisQueueName.js';
|
13
|
+
const DEFAULT_CONCURRENCY = 10;
|
13
14
|
/**
|
14
15
|
* the underlying class driving the `background` singleton,
|
15
16
|
* available as an import from `psychic-workers`.
|
@@ -126,13 +127,15 @@ export class Background {
|
|
126
127
|
}
|
127
128
|
async shutdownAndExit() {
|
128
129
|
await this.shutdown();
|
129
|
-
|
130
|
+
// https://docs.bullmq.io/guide/going-to-production#gracefully-shut-down-workers
|
131
|
+
process.exit(0);
|
130
132
|
}
|
131
133
|
/**
|
132
134
|
* Shuts down workers, closes all redis connections
|
133
135
|
*/
|
134
136
|
async shutdown() {
|
135
|
-
|
137
|
+
if (!EnvInternal.isTest)
|
138
|
+
PsychicApp.log(`[psychic-workers] shutdown`);
|
136
139
|
const psychicWorkersApp = PsychicAppWorkers.getOrFail();
|
137
140
|
for (const hook of psychicWorkersApp.hooks.workerShutdown) {
|
138
141
|
await hook();
|
@@ -144,18 +147,18 @@ export class Background {
|
|
144
147
|
* closes all redis connections for workers and queues
|
145
148
|
*/
|
146
149
|
async closeAllRedisConnections() {
|
147
|
-
|
148
|
-
|
149
|
-
}
|
150
|
+
if (!EnvInternal.isTest)
|
151
|
+
PsychicApp.log(`[psychic-workers] closeAllRedisConnections`);
|
150
152
|
for (const worker of this.workers) {
|
151
153
|
await worker.close();
|
152
154
|
}
|
153
155
|
for (const connection of this.redisConnections) {
|
154
156
|
try {
|
155
|
-
connection.
|
157
|
+
await connection.quit();
|
156
158
|
}
|
157
|
-
catch {
|
158
|
-
|
159
|
+
catch (error) {
|
160
|
+
if (!EnvInternal.isTest)
|
161
|
+
PsychicApp.logWithLevel('error', `[psychic-workers] error quitting Redis:`, error);
|
159
162
|
}
|
160
163
|
}
|
161
164
|
}
|
@@ -201,7 +204,7 @@ export class Background {
|
|
201
204
|
for (let i = 0; i < workerCount; i++) {
|
202
205
|
this._workers.push(new Background.Worker(formattedQueueName, async (job) => await this.doWork(job), {
|
203
206
|
connection: defaultWorkerConnection,
|
204
|
-
concurrency: backgroundOptions.defaultWorkstream?.concurrency ||
|
207
|
+
concurrency: backgroundOptions.defaultWorkstream?.concurrency || DEFAULT_CONCURRENCY,
|
205
208
|
}));
|
206
209
|
}
|
207
210
|
}
|
@@ -248,7 +251,7 @@ export class Background {
|
|
248
251
|
limit: namedWorkstream.rateLimit,
|
249
252
|
},
|
250
253
|
connection: namedWorkstreamWorkerConnection,
|
251
|
-
concurrency: namedWorkstream.concurrency ||
|
254
|
+
concurrency: namedWorkstream.concurrency || DEFAULT_CONCURRENCY,
|
252
255
|
// explicitly typing as WorkerOptions because Psychic can't be aware of BullMQ Pro options
|
253
256
|
}));
|
254
257
|
}
|
@@ -367,11 +370,15 @@ export class Background {
|
|
367
370
|
work() {
|
368
371
|
this.connect({ activateWorkers: true });
|
369
372
|
process.on('SIGTERM', () => {
|
373
|
+
if (!EnvInternal.isTest)
|
374
|
+
PsychicApp.log('[psychic-workers] handle SIGTERM');
|
370
375
|
void this.shutdownAndExit()
|
371
376
|
.then(() => { })
|
372
377
|
.catch(() => { });
|
373
378
|
});
|
374
379
|
process.on('SIGINT', () => {
|
380
|
+
if (!EnvInternal.isTest)
|
381
|
+
PsychicApp.log('[psychic-workers] handle SIGINT');
|
375
382
|
void this.shutdownAndExit()
|
376
383
|
.then(() => { })
|
377
384
|
.catch(() => { });
|
@@ -388,7 +395,7 @@ export class Background {
|
|
388
395
|
* @param importKey - (optional) the import key for the class
|
389
396
|
* @param jobConfig - (optional) the background job config to use when backgrounding this method
|
390
397
|
*/
|
391
|
-
async staticMethod(ObjectClass, method, { globalName, delaySeconds, args = [], jobConfig = {}, }) {
|
398
|
+
async staticMethod(ObjectClass, method, { globalName, delaySeconds, jobId, args = [], jobConfig = {}, }) {
|
392
399
|
this.connect();
|
393
400
|
await this._addToQueue(`BackgroundJobQueueStaticJob`, {
|
394
401
|
globalName,
|
@@ -396,6 +403,7 @@ export class Background {
|
|
396
403
|
args,
|
397
404
|
}, {
|
398
405
|
delaySeconds,
|
406
|
+
jobId,
|
399
407
|
jobConfig,
|
400
408
|
groupId: this.jobConfigToGroupId(jobConfig),
|
401
409
|
priority: this.jobConfigToPriority(jobConfig),
|
@@ -468,7 +476,7 @@ export class Background {
|
|
468
476
|
* @param importKey - (optional) the import key for the class
|
469
477
|
* @param jobConfig - (optional) the background job config to use when backgrounding this method
|
470
478
|
*/
|
471
|
-
async modelInstanceMethod(modelInstance, method, { delaySeconds, args = [], jobConfig = {}, }) {
|
479
|
+
async modelInstanceMethod(modelInstance, method, { delaySeconds, jobId, args = [], jobConfig = {}, }) {
|
472
480
|
this.connect();
|
473
481
|
await this._addToQueue('BackgroundJobQueueModelInstanceJob', {
|
474
482
|
id: modelInstance.primaryKeyValue,
|
@@ -477,16 +485,19 @@ export class Background {
|
|
477
485
|
args,
|
478
486
|
}, {
|
479
487
|
delaySeconds,
|
488
|
+
jobId,
|
480
489
|
jobConfig,
|
481
490
|
groupId: this.jobConfigToGroupId(jobConfig),
|
482
491
|
priority: this.jobConfigToPriority(jobConfig),
|
483
492
|
});
|
484
493
|
}
|
485
494
|
// should be private, but public so we can test
|
486
|
-
async _addToQueue(jobType, jobData, { delaySeconds, jobConfig, priority, groupId, }) {
|
495
|
+
async _addToQueue(jobType, jobData, { delaySeconds, jobId, jobConfig, priority, groupId, }) {
|
487
496
|
// set this variable out side of the conditional so that
|
488
497
|
// mismatches will raise exceptions even in tests
|
489
498
|
const queueInstance = this.queueInstance(jobConfig);
|
499
|
+
// if delaySeconds is 0, we will intentionally treat
|
500
|
+
// this as `undefined`
|
490
501
|
const delay = delaySeconds ? delaySeconds * 1000 : undefined;
|
491
502
|
if (EnvInternal.isTest && !EnvInternal.boolean('REALLY_TEST_BACKGROUND_QUEUE')) {
|
492
503
|
const queue = new Background.Queue('TestQueue', { connection: {} });
|
@@ -500,6 +511,7 @@ export class Background {
|
|
500
511
|
if (groupId && priority) {
|
501
512
|
await queueInstance.add(jobType, jobData, {
|
502
513
|
delay,
|
514
|
+
jobId,
|
503
515
|
group: {
|
504
516
|
...this.groupIdToGroupConfig(groupId),
|
505
517
|
priority: this.mapPriorityWordToPriorityNumber(priority),
|
@@ -511,6 +523,7 @@ export class Background {
|
|
511
523
|
else {
|
512
524
|
await queueInstance.add(jobType, jobData, {
|
513
525
|
delay,
|
526
|
+
jobId,
|
514
527
|
group: this.groupIdToGroupConfig(groupId),
|
515
528
|
priority: this.mapPriorityWordToPriorityNumber(priority),
|
516
529
|
// explicitly typing as JobsOptions because Psychic can't be aware of BullMQ Pro options
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Dream } from '@rvoh/dream';
|
2
|
-
import { BackgroundJobConfig } from '../types/background.js';
|
2
|
+
import { BackgroundJobConfig, DelayedJobOpts } from '../types/background.js';
|
3
3
|
import { FunctionPropertyNames } from '../types/utils.js';
|
4
4
|
import { BackgroundableMethodArgs } from './BaseBackgroundedService.js';
|
5
5
|
export default class BaseBackgroundedModel extends Dream {
|
@@ -64,7 +64,7 @@ export default class BaseBackgroundedModel extends Dream {
|
|
64
64
|
* @param methodName - the name of the static method you wish to run in the background
|
65
65
|
* @param args - a variadic list of arguments to be sent to your method
|
66
66
|
*/
|
67
|
-
static backgroundWithDelay<T, MethodName extends PsychicBackgroundedModelStaticMethods<T & typeof BaseBackgroundedModel>, MethodFunc extends T[MethodName & keyof T], MethodArgs extends BackgroundableMethodArgs<MethodFunc>>(this: T,
|
67
|
+
static backgroundWithDelay<T, MethodName extends PsychicBackgroundedModelStaticMethods<T & typeof BaseBackgroundedModel>, MethodFunc extends T[MethodName & keyof T], MethodArgs extends BackgroundableMethodArgs<MethodFunc>>(this: T, delay: DelayedJobOpts, methodName: MethodName, ...args: MethodArgs): Promise<void>;
|
68
68
|
/**
|
69
69
|
* types composed by psychic must be provided, since psychic-workers leverages
|
70
70
|
* the sync command in psychic to read your backgroundable services and extract
|
@@ -114,7 +114,7 @@ export default class BaseBackgroundedModel extends Dream {
|
|
114
114
|
* @param methodName - the name of the static method you wish to run in the background
|
115
115
|
* @param args - a variadic list of arguments to be sent to your method
|
116
116
|
*/
|
117
|
-
backgroundWithDelay<T, MethodName extends PsychicBackgroundedServiceInstanceMethods<T & BaseBackgroundedModel>, MethodFunc extends T[MethodName & keyof T], MethodArgs extends BackgroundableMethodArgs<MethodFunc>>(this: T,
|
117
|
+
backgroundWithDelay<T, MethodName extends PsychicBackgroundedServiceInstanceMethods<T & BaseBackgroundedModel>, MethodFunc extends T[MethodName & keyof T], MethodArgs extends BackgroundableMethodArgs<MethodFunc>>(this: T, delay: DelayedJobOpts, methodName: MethodName, ...args: MethodArgs): Promise<void>;
|
118
118
|
}
|
119
119
|
export type PsychicBackgroundedModelStaticMethods<T extends typeof BaseBackgroundedModel> = Exclude<FunctionPropertyNames<Required<T>>, FunctionPropertyNames<typeof BaseBackgroundedModel>>;
|
120
120
|
export type PsychicBackgroundedServiceInstanceMethods<T extends BaseBackgroundedModel> = Exclude<FunctionPropertyNames<Required<T>>, FunctionPropertyNames<BaseBackgroundedModel>>;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Job } from 'bullmq';
|
2
|
-
import { BackgroundJobConfig } from '../types/background.js';
|
2
|
+
import { BackgroundJobConfig, DelayedJobOpts } from '../types/background.js';
|
3
3
|
import { FunctionPropertyNames } from '../types/utils.js';
|
4
4
|
export default class BaseBackgroundedService {
|
5
5
|
/**
|
@@ -72,7 +72,7 @@ export default class BaseBackgroundedService {
|
|
72
72
|
* @param methodName - the name of the static method you wish to run in the background
|
73
73
|
* @param args - a variadic list of arguments to be sent to your method
|
74
74
|
*/
|
75
|
-
static backgroundWithDelay<T, MethodName extends PsychicBackgroundedServiceStaticMethods<T & typeof BaseBackgroundedService>, MethodFunc extends T[MethodName & keyof T], MethodArgs extends BackgroundableMethodArgs<MethodFunc>>(this: T,
|
75
|
+
static backgroundWithDelay<T, MethodName extends PsychicBackgroundedServiceStaticMethods<T & typeof BaseBackgroundedService>, MethodFunc extends T[MethodName & keyof T], MethodArgs extends BackgroundableMethodArgs<MethodFunc>>(this: T, delay: DelayedJobOpts, methodName: MethodName, ...args: MethodArgs): Promise<void>;
|
76
76
|
/**
|
77
77
|
* types composed by psychic must be provided, since psychic-workers leverages
|
78
78
|
* the sync command in psychic to read your backgroundable services and extract
|
@@ -124,11 +124,12 @@ export declare class Background {
|
|
124
124
|
* @param importKey - (optional) the import key for the class
|
125
125
|
* @param jobConfig - (optional) the background job config to use when backgrounding this method
|
126
126
|
*/
|
127
|
-
staticMethod(ObjectClass: Record<'name', string>, method: string, { globalName, delaySeconds, args, jobConfig, }: {
|
127
|
+
staticMethod(ObjectClass: Record<'name', string>, method: string, { globalName, delaySeconds, jobId, args, jobConfig, }: {
|
128
128
|
globalName: string;
|
129
129
|
args?: any[];
|
130
130
|
filepath?: string;
|
131
131
|
delaySeconds?: number;
|
132
|
+
jobId?: string | undefined;
|
132
133
|
importKey?: string;
|
133
134
|
jobConfig?: BackgroundJobConfig<any>;
|
134
135
|
}): Promise<void>;
|
@@ -162,14 +163,16 @@ export declare class Background {
|
|
162
163
|
* @param importKey - (optional) the import key for the class
|
163
164
|
* @param jobConfig - (optional) the background job config to use when backgrounding this method
|
164
165
|
*/
|
165
|
-
modelInstanceMethod(modelInstance: Dream, method: string, { delaySeconds, args, jobConfig, }: {
|
166
|
+
modelInstanceMethod(modelInstance: Dream, method: string, { delaySeconds, jobId, args, jobConfig, }: {
|
166
167
|
delaySeconds?: number;
|
168
|
+
jobId?: string | undefined;
|
167
169
|
importKey?: string;
|
168
170
|
args?: any[];
|
169
171
|
jobConfig?: BackgroundJobConfig<any>;
|
170
172
|
}): Promise<void>;
|
171
|
-
_addToQueue(jobType: JobTypes, jobData: BackgroundJobData, { delaySeconds, jobConfig, priority, groupId, }: {
|
173
|
+
_addToQueue(jobType: JobTypes, jobData: BackgroundJobData, { delaySeconds, jobId, jobConfig, priority, groupId, }: {
|
172
174
|
delaySeconds?: number | undefined;
|
175
|
+
jobId?: string | undefined;
|
173
176
|
jobConfig: BackgroundJobConfig<any>;
|
174
177
|
priority: BackgroundQueuePriority;
|
175
178
|
groupId?: string | undefined;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Env } from '@rvoh/dream';
|
2
2
|
declare const EnvInternal: Env<{
|
3
3
|
string: "NODE_ENV" | "PSYCHIC_CORE_DEVELOPMENT";
|
4
|
-
boolean: "
|
5
|
-
}, "NODE_ENV" | "PSYCHIC_CORE_DEVELOPMENT", never, "
|
4
|
+
boolean: "REALLY_TEST_BACKGROUND_QUEUE";
|
5
|
+
}, "NODE_ENV" | "PSYCHIC_CORE_DEVELOPMENT", never, "REALLY_TEST_BACKGROUND_QUEUE">;
|
6
6
|
export default EnvInternal;
|
@@ -30,6 +30,20 @@ export interface BackgroundJobData {
|
|
30
30
|
*/
|
31
31
|
globalName?: string;
|
32
32
|
}
|
33
|
+
export type DelayedJobOpts = DelayedJobDuration & {
|
34
|
+
/**
|
35
|
+
* a unique identifier for your job. this identifier will be
|
36
|
+
* used to debounce, leveraging the internal throttling mechanisms
|
37
|
+
* provided by BullMQ
|
38
|
+
*/
|
39
|
+
jobId?: string;
|
40
|
+
};
|
41
|
+
export interface DelayedJobDuration {
|
42
|
+
seconds?: number;
|
43
|
+
minutes?: number;
|
44
|
+
hours?: number;
|
45
|
+
days?: number;
|
46
|
+
}
|
33
47
|
export type JobTypes = 'BackgroundJobQueueFunctionJob' | 'BackgroundJobQueueStaticJob' | 'BackgroundJobQueueModelInstanceJob';
|
34
48
|
export type BackgroundQueuePriority = 'default' | 'urgent' | 'not_urgent' | 'last';
|
35
49
|
interface BaseBackgroundJobConfig {
|
package/package.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"type": "module",
|
3
3
|
"name": "@rvoh/psychic-workers",
|
4
4
|
"description": "Background job system for Psychic applications",
|
5
|
-
"version": "0.
|
5
|
+
"version": "0.4.1",
|
6
6
|
"author": "RVO Health",
|
7
7
|
"repository": {
|
8
8
|
"type": "git",
|
@@ -73,4 +73,4 @@
|
|
73
73
|
"vitest": "^3.1.1"
|
74
74
|
},
|
75
75
|
"packageManager": "yarn@4.7.0"
|
76
|
-
}
|
76
|
+
}
|