@rvoh/psychic-workers 0.3.2 → 0.4.0

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.
@@ -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(delaySeconds, methodName, ...args) {
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(delaySeconds, methodName, ...args) {
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(delaySeconds, methodName, ...args) {
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,14 @@ class Background {
130
131
  }
131
132
  async shutdownAndExit() {
132
133
  await this.shutdown();
133
- process.exit();
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
- await Promise.all(this._workers.map(worker => worker.close()));
141
+ index_js_1.default.getOrFail().psychicApp.logger.info(`[psychic-workers] shutdown`);
140
142
  const psychicWorkersApp = index_js_1.default.getOrFail();
141
143
  for (const hook of psychicWorkersApp.hooks.workerShutdown) {
142
144
  await hook();
@@ -148,19 +150,12 @@ class Background {
148
150
  * closes all redis connections for workers and queues
149
151
  */
150
152
  async closeAllRedisConnections() {
151
- for (const queue of this.queues) {
152
- await queue.close();
153
- }
153
+ index_js_1.default.getOrFail().psychicApp.logger.info(`[psychic-workers] closeAllRedisConnections`);
154
154
  for (const worker of this.workers) {
155
155
  await worker.close();
156
156
  }
157
157
  for (const connection of this.redisConnections) {
158
- try {
159
- connection.disconnect();
160
- }
161
- catch {
162
- // noop
163
- }
158
+ await connection.quit();
164
159
  }
165
160
  }
166
161
  /**
@@ -205,7 +200,7 @@ class Background {
205
200
  for (let i = 0; i < workerCount; i++) {
206
201
  this._workers.push(new Background.Worker(formattedQueueName, async (job) => await this.doWork(job), {
207
202
  connection: defaultWorkerConnection,
208
- concurrency: backgroundOptions.defaultWorkstream?.concurrency || 1,
203
+ concurrency: backgroundOptions.defaultWorkstream?.concurrency || DEFAULT_CONCURRENCY,
209
204
  }));
210
205
  }
211
206
  }
@@ -252,7 +247,7 @@ class Background {
252
247
  limit: namedWorkstream.rateLimit,
253
248
  },
254
249
  connection: namedWorkstreamWorkerConnection,
255
- concurrency: namedWorkstream.concurrency || 1,
250
+ concurrency: namedWorkstream.concurrency || DEFAULT_CONCURRENCY,
256
251
  // explicitly typing as WorkerOptions because Psychic can't be aware of BullMQ Pro options
257
252
  }));
258
253
  }
@@ -371,11 +366,13 @@ class Background {
371
366
  work() {
372
367
  this.connect({ activateWorkers: true });
373
368
  process.on('SIGTERM', () => {
369
+ index_js_1.default.getOrFail().psychicApp.logger.info('[psychic-workers] handle SIGTERM');
374
370
  void this.shutdownAndExit()
375
371
  .then(() => { })
376
372
  .catch(() => { });
377
373
  });
378
374
  process.on('SIGINT', () => {
375
+ index_js_1.default.getOrFail().psychicApp.logger.info('[psychic-workers] handle SIGINT');
379
376
  void this.shutdownAndExit()
380
377
  .then(() => { })
381
378
  .catch(() => { });
@@ -392,7 +389,7 @@ class Background {
392
389
  * @param importKey - (optional) the import key for the class
393
390
  * @param jobConfig - (optional) the background job config to use when backgrounding this method
394
391
  */
395
- async staticMethod(ObjectClass, method, { globalName, delaySeconds, args = [], jobConfig = {}, }) {
392
+ async staticMethod(ObjectClass, method, { globalName, delaySeconds, jobId, args = [], jobConfig = {}, }) {
396
393
  this.connect();
397
394
  await this._addToQueue(`BackgroundJobQueueStaticJob`, {
398
395
  globalName,
@@ -400,6 +397,7 @@ class Background {
400
397
  args,
401
398
  }, {
402
399
  delaySeconds,
400
+ jobId,
403
401
  jobConfig,
404
402
  groupId: this.jobConfigToGroupId(jobConfig),
405
403
  priority: this.jobConfigToPriority(jobConfig),
@@ -472,7 +470,7 @@ class Background {
472
470
  * @param importKey - (optional) the import key for the class
473
471
  * @param jobConfig - (optional) the background job config to use when backgrounding this method
474
472
  */
475
- async modelInstanceMethod(modelInstance, method, { delaySeconds, args = [], jobConfig = {}, }) {
473
+ async modelInstanceMethod(modelInstance, method, { delaySeconds, jobId, args = [], jobConfig = {}, }) {
476
474
  this.connect();
477
475
  await this._addToQueue('BackgroundJobQueueModelInstanceJob', {
478
476
  id: modelInstance.primaryKeyValue,
@@ -481,16 +479,19 @@ class Background {
481
479
  args,
482
480
  }, {
483
481
  delaySeconds,
482
+ jobId,
484
483
  jobConfig,
485
484
  groupId: this.jobConfigToGroupId(jobConfig),
486
485
  priority: this.jobConfigToPriority(jobConfig),
487
486
  });
488
487
  }
489
488
  // should be private, but public so we can test
490
- async _addToQueue(jobType, jobData, { delaySeconds, jobConfig, priority, groupId, }) {
489
+ async _addToQueue(jobType, jobData, { delaySeconds, jobId, jobConfig, priority, groupId, }) {
491
490
  // set this variable out side of the conditional so that
492
491
  // mismatches will raise exceptions even in tests
493
492
  const queueInstance = this.queueInstance(jobConfig);
493
+ // if delaySeconds is 0, we will intentionally treat
494
+ // this as `undefined`
494
495
  const delay = delaySeconds ? delaySeconds * 1000 : undefined;
495
496
  if (EnvInternal_js_1.default.isTest && !EnvInternal_js_1.default.boolean('REALLY_TEST_BACKGROUND_QUEUE')) {
496
497
  const queue = new Background.Queue('TestQueue', { connection: {} });
@@ -504,6 +505,7 @@ class Background {
504
505
  if (groupId && priority) {
505
506
  await queueInstance.add(jobType, jobData, {
506
507
  delay,
508
+ jobId,
507
509
  group: {
508
510
  ...this.groupIdToGroupConfig(groupId),
509
511
  priority: this.mapPriorityWordToPriorityNumber(priority),
@@ -515,6 +517,7 @@ class Background {
515
517
  else {
516
518
  await queueInstance.add(jobType, jobData, {
517
519
  delay,
520
+ jobId,
518
521
  group: this.groupIdToGroupConfig(groupId),
519
522
  priority: this.mapPriorityWordToPriorityNumber(priority),
520
523
  // 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(delaySeconds, methodName, ...args) {
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(delaySeconds, methodName, ...args) {
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(delaySeconds, methodName, ...args) {
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,14 @@ export class Background {
126
127
  }
127
128
  async shutdownAndExit() {
128
129
  await this.shutdown();
129
- process.exit();
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
- await Promise.all(this._workers.map(worker => worker.close()));
137
+ PsychicAppWorkers.getOrFail().psychicApp.logger.info(`[psychic-workers] shutdown`);
136
138
  const psychicWorkersApp = PsychicAppWorkers.getOrFail();
137
139
  for (const hook of psychicWorkersApp.hooks.workerShutdown) {
138
140
  await hook();
@@ -144,19 +146,12 @@ export class Background {
144
146
  * closes all redis connections for workers and queues
145
147
  */
146
148
  async closeAllRedisConnections() {
147
- for (const queue of this.queues) {
148
- await queue.close();
149
- }
149
+ PsychicAppWorkers.getOrFail().psychicApp.logger.info(`[psychic-workers] closeAllRedisConnections`);
150
150
  for (const worker of this.workers) {
151
151
  await worker.close();
152
152
  }
153
153
  for (const connection of this.redisConnections) {
154
- try {
155
- connection.disconnect();
156
- }
157
- catch {
158
- // noop
159
- }
154
+ await connection.quit();
160
155
  }
161
156
  }
162
157
  /**
@@ -201,7 +196,7 @@ export class Background {
201
196
  for (let i = 0; i < workerCount; i++) {
202
197
  this._workers.push(new Background.Worker(formattedQueueName, async (job) => await this.doWork(job), {
203
198
  connection: defaultWorkerConnection,
204
- concurrency: backgroundOptions.defaultWorkstream?.concurrency || 1,
199
+ concurrency: backgroundOptions.defaultWorkstream?.concurrency || DEFAULT_CONCURRENCY,
205
200
  }));
206
201
  }
207
202
  }
@@ -248,7 +243,7 @@ export class Background {
248
243
  limit: namedWorkstream.rateLimit,
249
244
  },
250
245
  connection: namedWorkstreamWorkerConnection,
251
- concurrency: namedWorkstream.concurrency || 1,
246
+ concurrency: namedWorkstream.concurrency || DEFAULT_CONCURRENCY,
252
247
  // explicitly typing as WorkerOptions because Psychic can't be aware of BullMQ Pro options
253
248
  }));
254
249
  }
@@ -367,11 +362,13 @@ export class Background {
367
362
  work() {
368
363
  this.connect({ activateWorkers: true });
369
364
  process.on('SIGTERM', () => {
365
+ PsychicAppWorkers.getOrFail().psychicApp.logger.info('[psychic-workers] handle SIGTERM');
370
366
  void this.shutdownAndExit()
371
367
  .then(() => { })
372
368
  .catch(() => { });
373
369
  });
374
370
  process.on('SIGINT', () => {
371
+ PsychicAppWorkers.getOrFail().psychicApp.logger.info('[psychic-workers] handle SIGINT');
375
372
  void this.shutdownAndExit()
376
373
  .then(() => { })
377
374
  .catch(() => { });
@@ -388,7 +385,7 @@ export class Background {
388
385
  * @param importKey - (optional) the import key for the class
389
386
  * @param jobConfig - (optional) the background job config to use when backgrounding this method
390
387
  */
391
- async staticMethod(ObjectClass, method, { globalName, delaySeconds, args = [], jobConfig = {}, }) {
388
+ async staticMethod(ObjectClass, method, { globalName, delaySeconds, jobId, args = [], jobConfig = {}, }) {
392
389
  this.connect();
393
390
  await this._addToQueue(`BackgroundJobQueueStaticJob`, {
394
391
  globalName,
@@ -396,6 +393,7 @@ export class Background {
396
393
  args,
397
394
  }, {
398
395
  delaySeconds,
396
+ jobId,
399
397
  jobConfig,
400
398
  groupId: this.jobConfigToGroupId(jobConfig),
401
399
  priority: this.jobConfigToPriority(jobConfig),
@@ -468,7 +466,7 @@ export class Background {
468
466
  * @param importKey - (optional) the import key for the class
469
467
  * @param jobConfig - (optional) the background job config to use when backgrounding this method
470
468
  */
471
- async modelInstanceMethod(modelInstance, method, { delaySeconds, args = [], jobConfig = {}, }) {
469
+ async modelInstanceMethod(modelInstance, method, { delaySeconds, jobId, args = [], jobConfig = {}, }) {
472
470
  this.connect();
473
471
  await this._addToQueue('BackgroundJobQueueModelInstanceJob', {
474
472
  id: modelInstance.primaryKeyValue,
@@ -477,16 +475,19 @@ export class Background {
477
475
  args,
478
476
  }, {
479
477
  delaySeconds,
478
+ jobId,
480
479
  jobConfig,
481
480
  groupId: this.jobConfigToGroupId(jobConfig),
482
481
  priority: this.jobConfigToPriority(jobConfig),
483
482
  });
484
483
  }
485
484
  // should be private, but public so we can test
486
- async _addToQueue(jobType, jobData, { delaySeconds, jobConfig, priority, groupId, }) {
485
+ async _addToQueue(jobType, jobData, { delaySeconds, jobId, jobConfig, priority, groupId, }) {
487
486
  // set this variable out side of the conditional so that
488
487
  // mismatches will raise exceptions even in tests
489
488
  const queueInstance = this.queueInstance(jobConfig);
489
+ // if delaySeconds is 0, we will intentionally treat
490
+ // this as `undefined`
490
491
  const delay = delaySeconds ? delaySeconds * 1000 : undefined;
491
492
  if (EnvInternal.isTest && !EnvInternal.boolean('REALLY_TEST_BACKGROUND_QUEUE')) {
492
493
  const queue = new Background.Queue('TestQueue', { connection: {} });
@@ -500,6 +501,7 @@ export class Background {
500
501
  if (groupId && priority) {
501
502
  await queueInstance.add(jobType, jobData, {
502
503
  delay,
504
+ jobId,
503
505
  group: {
504
506
  ...this.groupIdToGroupConfig(groupId),
505
507
  priority: this.mapPriorityWordToPriorityNumber(priority),
@@ -511,6 +513,7 @@ export class Background {
511
513
  else {
512
514
  await queueInstance.add(jobType, jobData, {
513
515
  delay,
516
+ jobId,
514
517
  group: this.groupIdToGroupConfig(groupId),
515
518
  priority: this.mapPriorityWordToPriorityNumber(priority),
516
519
  // explicitly typing as JobsOptions because Psychic can't be aware of BullMQ Pro options
@@ -0,0 +1,6 @@
1
+ export default function durationToSeconds(duration) {
2
+ return ((duration.seconds ? duration.seconds : 0) +
3
+ (duration.minutes ? duration.minutes * 60 : 0) +
4
+ (duration.hours ? duration.hours * 60 * 60 : 0) +
5
+ (duration.days ? duration.days * 60 * 60 * 24 : 0));
6
+ }
@@ -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, delaySeconds: number, methodName: MethodName, ...args: MethodArgs): Promise<void>;
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, delaySeconds: number, methodName: MethodName, ...args: MethodArgs): Promise<void>;
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, delaySeconds: number, methodName: MethodName, ...args: MethodArgs): Promise<void>;
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;
@@ -0,0 +1,2 @@
1
+ import { DelayedJobDuration } from '../types/background.js';
2
+ export default function durationToSeconds(duration: DelayedJobDuration): number;
@@ -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.3.2",
5
+ "version": "0.4.0",
6
6
  "author": "RVO Health",
7
7
  "repository": {
8
8
  "type": "git",