@rvoh/psychic-workers 0.3.0 → 0.3.2

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.
Files changed (39) hide show
  1. package/dist/cjs/src/background/BaseBackgroundedModel.js +105 -0
  2. package/dist/cjs/src/background/BaseBackgroundedService.js +71 -0
  3. package/dist/cjs/src/background/BaseScheduledService.js +51 -0
  4. package/dist/cjs/src/background/helpers/nameToRedisQueueName.js +10 -0
  5. package/dist/cjs/src/background/index.js +144 -68
  6. package/dist/cjs/src/error/background/ActivatingBackgroundWorkersWithoutDefaultWorkerConnection.js +11 -0
  7. package/dist/cjs/src/error/background/ActivatingNamedQueueBackgroundWorkersWithoutWorkerConnection.js +17 -0
  8. package/dist/cjs/src/error/background/DefaultBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection.js +11 -0
  9. package/dist/cjs/src/error/background/NamedBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection.js +16 -0
  10. package/dist/cjs/src/psychic-app-workers/index.js +1 -1
  11. package/dist/cjs/src/types/utils.js +2 -0
  12. package/dist/esm/src/background/BaseBackgroundedModel.js +105 -0
  13. package/dist/esm/src/background/BaseBackgroundedService.js +71 -0
  14. package/dist/esm/src/background/BaseScheduledService.js +51 -0
  15. package/dist/esm/src/background/helpers/nameToRedisQueueName.js +7 -0
  16. package/dist/esm/src/background/index.js +134 -58
  17. package/dist/esm/src/error/background/ActivatingBackgroundWorkersWithoutDefaultWorkerConnection.js +8 -0
  18. package/dist/esm/src/error/background/ActivatingNamedQueueBackgroundWorkersWithoutWorkerConnection.js +14 -0
  19. package/dist/esm/src/error/background/DefaultBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection.js +8 -0
  20. package/dist/esm/src/error/background/NamedBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection.js +13 -0
  21. package/dist/esm/src/index.js +1 -1
  22. package/dist/esm/src/psychic-app-workers/index.js +1 -1
  23. package/dist/esm/src/types/utils.js +1 -0
  24. package/dist/types/src/background/BaseBackgroundedModel.d.ts +108 -3
  25. package/dist/types/src/background/BaseBackgroundedService.d.ts +73 -2
  26. package/dist/types/src/background/BaseScheduledService.d.ts +53 -2
  27. package/dist/types/src/background/helpers/nameToRedisQueueName.d.ts +2 -0
  28. package/dist/types/src/background/index.d.ts +117 -32
  29. package/dist/types/src/error/background/ActivatingBackgroundWorkersWithoutDefaultWorkerConnection.d.ts +3 -0
  30. package/dist/types/src/error/background/ActivatingNamedQueueBackgroundWorkersWithoutWorkerConnection.d.ts +5 -0
  31. package/dist/types/src/error/background/DefaultBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection.d.ts +3 -0
  32. package/dist/types/src/error/background/NamedBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection.d.ts +5 -0
  33. package/dist/types/src/index.d.ts +2 -1
  34. package/dist/types/src/psychic-app-workers/index.d.ts +4 -4
  35. package/dist/types/src/types/background.d.ts +47 -0
  36. package/package.json +2 -2
  37. /package/dist/cjs/src/{background/types.js → types/background.js} +0 -0
  38. /package/dist/esm/src/{background/types.js → types/background.js} +0 -0
  39. /package/dist/types/src/{background/types.d.ts → types/utils.d.ts} +0 -0
@@ -1,18 +1,62 @@
1
1
  import { GlobalNameNotSet } from '@rvoh/dream';
2
2
  import background from './index.js';
3
3
  export default class BaseBackgroundedService {
4
+ /**
5
+ * A getter meant to be overridden in child classes. This does
6
+ * not have to be explicitly provided, but if so, it would allow
7
+ * you to override the default behavior of anything backgrounded
8
+ * by this service, such as the priority or workstream.
9
+ *
10
+ * @returns {object} config - the background job config
11
+ * @returns {string} config.priority - 'default' | 'urgent' | 'not_urgent' | 'last'
12
+ * @returns {string} config.workstream - a workstream name. This would be the name of a workstream, as defined in conf/workers.ts
13
+ * @returns {string} config.queueId - the id of the BullMQ queue you wish to connect to. This can only be provided if workstream is not provided.
14
+ * @returns {string} config.groupId - the groupId of the BullMQ queue you wish to connect to. This can only be provided if workstream is not provided.
15
+ */
4
16
  static get backgroundJobConfig() {
5
17
  return {};
6
18
  }
19
+ /**
20
+ * @internal
21
+ *
22
+ * Returns a unique global name for the given service.
23
+ *
24
+ * @returns A string representing a unique key for this service
25
+ */
7
26
  static get globalName() {
8
27
  if (!this._globalName)
9
28
  throw new GlobalNameNotSet(this);
10
29
  return this._globalName;
11
30
  }
31
+ /**
32
+ * @internal
33
+ *
34
+ * Used by PsychicApplicationWorkers during the load process
35
+ * for services to assign unique global names to each service
36
+ * based on the file name of that model.
37
+ */
12
38
  static setGlobalName(globalName) {
13
39
  this._globalName = globalName;
14
40
  }
15
41
  static _globalName;
42
+ /**
43
+ * runs the specified method in a background queue, driven by BullMQ,
44
+ * sending in the provided args.
45
+ *
46
+ * ```ts
47
+ * await MyBackgroundableClass.background('myMethod', 'abc', 123)
48
+ * ```
49
+ * though calling background must be awaited, the resolution of the promise
50
+ * is an indication that the job was put in the queue, not that it has
51
+ * completed.
52
+ *
53
+ * NOTE: in test environments, psychic will immediately invoke the underlying
54
+ * method, preventing you from needing to explicitly wait for queues to flush
55
+ * before making assertions.
56
+ *
57
+ * @param methodName - the name of the static method you wish to run in the background
58
+ * @param args - a variadic list of arguments to be sent to your method
59
+ */
16
60
  static async background(methodName, ...args) {
17
61
  const safeThis = this;
18
62
  return await background.staticMethod(safeThis, methodName, {
@@ -21,6 +65,27 @@ export default class BaseBackgroundedService {
21
65
  jobConfig: safeThis.backgroundJobConfig,
22
66
  });
23
67
  }
68
+ /**
69
+ * runs the specified method in a background queue, driven by BullMQ,
70
+ * sending in the provided args, including a delay in seconds, which
71
+ * can be used to hold off the job for a certain amount of time after
72
+ * it is entered into the queue.
73
+ *
74
+ * ```ts
75
+ * await MyBackgroundableClass.backgroundWithDelay('myMethod', 'abc', 123)
76
+ * ```
77
+ * though calling background must be awaited, the resolution of the promise
78
+ * is an indication that the job was put in the queue, not that it has
79
+ * completed.
80
+ *
81
+ * NOTE: in test environments, psychic will immediately invoke the underlying
82
+ * method, preventing you from needing to explicitly wait for queues to flush
83
+ * before making assertions.
84
+ *
85
+ * @param delaySeconds - the amount of time (in seconds) you want to hold off before allowing the job to run
86
+ * @param methodName - the name of the static method you wish to run in the background
87
+ * @param args - a variadic list of arguments to be sent to your method
88
+ */
24
89
  static async backgroundWithDelay(delaySeconds, methodName, ...args) {
25
90
  const safeThis = this;
26
91
  return await background.staticMethod(safeThis, methodName, {
@@ -30,6 +95,12 @@ export default class BaseBackgroundedService {
30
95
  jobConfig: safeThis.backgroundJobConfig,
31
96
  });
32
97
  }
98
+ /**
99
+ * types composed by psychic must be provided, since psychic-workers leverages
100
+ * the sync command in psychic to read your backgroundable services and extract
101
+ * metadata, which can be used to help provide types for the underlying methods
102
+ * in psychic-workers.
103
+ */
33
104
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
105
  get psychicTypes() {
35
106
  throw new Error('Must define psychicTypes getter in BackgroundedService class within your application');
@@ -1,18 +1,63 @@
1
1
  import { GlobalNameNotSet } from '@rvoh/dream';
2
2
  import background from './index.js';
3
3
  export default class BaseScheduledService {
4
+ /**
5
+ * A getter meant to be overridden in child classes. This does
6
+ * not have to be explicitly provided, but if so, it would allow
7
+ * you to override the default behavior of anything backgrounded
8
+ * by this service, such as the priority or workstream.
9
+ *
10
+ * @returns {object} config - the background job config
11
+ * @returns {string} config.priority - 'default' | 'urgent' | 'not_urgent' | 'last'
12
+ * @returns {string} config.workstream - a workstream name. This would be the name of a workstream, as defined in conf/workers.ts
13
+ * @returns {string} config.queueId - the id of the BullMQ queue you wish to connect to. This can only be provided if workstream is not provided.
14
+ * @returns {string} config.groupId - the groupId of the BullMQ queue you wish to connect to. This can only be provided if workstream is not provided.
15
+ */
4
16
  static get backgroundJobConfig() {
5
17
  return {};
6
18
  }
19
+ /**
20
+ * @internal
21
+ *
22
+ * Returns a unique global name for the given service.
23
+ *
24
+ * @returns A string representing a unique key for this service
25
+ */
7
26
  static get globalName() {
8
27
  if (!this._globalName)
9
28
  throw new GlobalNameNotSet(this);
10
29
  return this._globalName;
11
30
  }
31
+ /**
32
+ * @internal
33
+ *
34
+ * Used by PsychicApplicationWorkers during the load process
35
+ * for services to assign unique global names to each service
36
+ * based on the file name of that model.
37
+ */
12
38
  static setGlobalName(globalName) {
13
39
  this._globalName = globalName;
14
40
  }
15
41
  static _globalName;
42
+ /**
43
+ * Schedules a job to be run repeatedly at a certain cron interval
44
+ * sending in the provided args.
45
+ *
46
+ * ```ts
47
+ * await MySchedulableClass.schedule('0 * * * *', 'myHourlyMethod', 'abc', 123)
48
+ * ```
49
+ * though calling background must be awaited, the resolution of the promise
50
+ * is an indication that the job was put in the queue, not that it has
51
+ * completed.
52
+ *
53
+ * NOTE: in test environments, psychic will immediately invoke the underlying
54
+ * method, preventing you from needing to explicitly wait for queues to flush
55
+ * before making assertions.
56
+ *
57
+ * @param pattern - A cron string representing the time interval you wish this to run on
58
+ * @param methodName - the name of the static method you wish to run in the background
59
+ * @param args - a variadic list of arguments to be sent to your method
60
+ */
16
61
  static async schedule(pattern, methodName, ...args) {
17
62
  const safeThis = this;
18
63
  return await background.scheduledMethod(safeThis, pattern, methodName, {
@@ -21,6 +66,12 @@ export default class BaseScheduledService {
21
66
  jobConfig: safeThis.backgroundJobConfig,
22
67
  });
23
68
  }
69
+ /**
70
+ * types composed by psychic must be provided, since psychic-workers leverages
71
+ * the sync command in psychic to read your backgroundable services and extract
72
+ * metadata, which can be used to help provide types for the underlying methods
73
+ * in psychic-workers.
74
+ */
24
75
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
76
  get psychicTypes() {
26
77
  throw new Error('Must define psychicTypes getter in BackgroundedService class within your application');
@@ -0,0 +1,7 @@
1
+ import { Cluster } from 'ioredis';
2
+ export default function nameToRedisQueueName(queueName, redis) {
3
+ queueName = queueName.replace(/\{|\}/g, '');
4
+ if (redis instanceof Cluster)
5
+ return `{${queueName}}`;
6
+ return queueName;
7
+ }
@@ -1,87 +1,100 @@
1
1
  import { closeAllDbConnections, compact, pascalize } from '@rvoh/dream';
2
2
  import { PsychicApp } from '@rvoh/psychic';
3
3
  import { Job, Queue, Worker } from 'bullmq';
4
- import { Cluster } from 'ioredis';
4
+ import ActivatingBackgroundWorkersWithoutDefaultWorkerConnection from '../error/background/ActivatingBackgroundWorkersWithoutDefaultWorkerConnection.js';
5
+ import ActivatingNamedQueueBackgroundWorkersWithoutWorkerConnection from '../error/background/ActivatingNamedQueueBackgroundWorkersWithoutWorkerConnection.js';
6
+ import DefaultBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection from '../error/background/DefaultBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection.js';
7
+ import NamedBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection from '../error/background/NamedBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection.js';
5
8
  import NoQueueForSpecifiedQueueName from '../error/background/NoQueueForSpecifiedQueueName.js';
6
9
  import NoQueueForSpecifiedWorkstream from '../error/background/NoQueueForSpecifiedWorkstream.js';
7
10
  import EnvInternal from '../helpers/EnvInternal.js';
8
11
  import PsychicAppWorkers from '../psychic-app-workers/index.js';
9
- class DefaultBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection extends Error {
10
- get message() {
11
- return `
12
- Native BullMQ options don't include a default queue connection, and the
13
- default config does not include a queue connection
14
- `;
15
- }
16
- }
17
- class NamedBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection extends Error {
18
- queueName;
19
- constructor(queueName) {
20
- super();
21
- this.queueName = queueName;
22
- }
23
- get message() {
24
- return `
25
- Native BullMQ options don't include a default queue connection, and the
26
- ${this.queueName} queue does not include a queue connection
27
- `;
28
- }
29
- }
30
- class ActivatingBackgroundWorkersWithoutDefaultWorkerConnection extends Error {
31
- get message() {
32
- return `
33
- defaultWorkerConnection is required when activating workers. For example,
34
- it may be omitted on webserver instances, but is required on worker instances.
35
- `;
36
- }
37
- }
38
- class ActivatingNamedQueueBackgroundWorkersWithoutWorkerConnection extends Error {
39
- queueName;
40
- constructor(queueName) {
41
- super();
42
- this.queueName = queueName;
43
- }
44
- get message() {
45
- return `
46
- defaultWorkerConnection is missing, and the ${this.queueName} queue does not
47
- specify a workerConnection. A worker connection isrequired when activating workers.
48
- For example, it may be omitted on webserver instances, but is required on worker instances.
49
- `;
50
- }
51
- }
12
+ import nameToRedisQueueName from './helpers/nameToRedisQueueName.js';
13
+ /**
14
+ * the underlying class driving the `background` singleton,
15
+ * available as an import from `psychic-workers`.
16
+ */
52
17
  export class Background {
18
+ /**
19
+ * returns the default queue name for your app
20
+ */
53
21
  static get defaultQueueName() {
54
22
  const psychicWorkersApp = PsychicAppWorkers.getOrFail();
55
23
  return `${pascalize(psychicWorkersApp.psychicApp.appName)}BackgroundJobQueue`;
56
24
  }
25
+ /**
26
+ * @internal
27
+ *
28
+ * returns the provided Worker class, or the Worker class from BullMQ
29
+ * if no override was provided. This is providable because BullMQ also
30
+ * offers a pro version, which requires you to provide custom classes.
31
+ */
57
32
  static get Worker() {
58
33
  const psychicWorkersApp = PsychicAppWorkers.getOrFail();
59
34
  return (psychicWorkersApp.backgroundOptions.providers?.Worker || Worker);
60
35
  }
36
+ /**
37
+ * @internal
38
+ *
39
+ * returns the provided Queue class, or the Queue class from BullMQ
40
+ * if no override was provided. This is providable because BullMQ also
41
+ * offers a pro version, which requires you to provide custom classes.
42
+ */
61
43
  static get Queue() {
62
44
  const psychicWorkersApp = PsychicAppWorkers.getOrFail();
63
45
  return (psychicWorkersApp.backgroundOptions.providers?.Queue || Queue);
64
46
  }
65
47
  /**
48
+ * @internal
49
+ *
66
50
  * Used when adding jobs to the default queue
67
51
  */
68
52
  defaultQueue = null;
69
53
  /**
54
+ * @internal
55
+ *
70
56
  * Used when adding jobs to the default transitional queue
71
57
  */
72
58
  defaultTransitionalQueue = null;
73
59
  /**
60
+ * @internal
61
+ *
74
62
  * Used when adding jobs to a named queue
75
63
  */
76
64
  namedQueues = {};
65
+ /**
66
+ * @internal
67
+ *
68
+ * Used when adding grouped jobs
69
+ */
77
70
  groupNames = {};
71
+ /**
72
+ * @internal
73
+ *
74
+ * Used when adding workstreams
75
+ */
78
76
  workstreamNames = [];
79
77
  /**
78
+ * @internal
79
+ *
80
80
  * Used when adding jobs to a named transitioanl queue
81
81
  */
82
82
  namedTransitionalQueues = {};
83
+ /**
84
+ * @internal
85
+ *
86
+ * All of the workers that are currently registered
87
+ */
83
88
  _workers = [];
89
+ /**
90
+ * @internal
91
+ *
92
+ * All of the redis connections that are currently registered
93
+ */
84
94
  redisConnections = [];
95
+ /**
96
+ * Establishes connection to BullMQ via redis
97
+ */
85
98
  connect({ activateWorkers = false, } = {}) {
86
99
  if (this.defaultQueue)
87
100
  return;
@@ -94,6 +107,9 @@ export class Background {
94
107
  this.simpleConnect(defaultBullMQQueueOptions, psychicWorkersApp.backgroundOptions, { activateWorkers });
95
108
  }
96
109
  }
110
+ /**
111
+ * Returns all the queues in your application
112
+ */
97
113
  get queues() {
98
114
  return compact([
99
115
  this.defaultQueue,
@@ -102,6 +118,9 @@ export class Background {
102
118
  ...Object.values(this.namedTransitionalQueues).map(queue => queue),
103
119
  ]);
104
120
  }
121
+ /**
122
+ * Returns all the workers in your application
123
+ */
105
124
  get workers() {
106
125
  return [...this._workers];
107
126
  }
@@ -109,6 +128,9 @@ export class Background {
109
128
  await this.shutdown();
110
129
  process.exit();
111
130
  }
131
+ /**
132
+ * Shuts down workers, closes all redis connections
133
+ */
112
134
  async shutdown() {
113
135
  await Promise.all(this._workers.map(worker => worker.close()));
114
136
  const psychicWorkersApp = PsychicAppWorkers.getOrFail();
@@ -118,6 +140,9 @@ export class Background {
118
140
  await closeAllDbConnections();
119
141
  await this.closeAllRedisConnections();
120
142
  }
143
+ /**
144
+ * closes all redis connections for workers and queues
145
+ */
121
146
  async closeAllRedisConnections() {
122
147
  for (const queue of this.queues) {
123
148
  await queue.close();
@@ -134,6 +159,11 @@ export class Background {
134
159
  }
135
160
  }
136
161
  }
162
+ /**
163
+ * @internal
164
+ *
165
+ * connects to BullMQ using workstream-based arguments
166
+ */
137
167
  simpleConnect(defaultBullMQQueueOptions, backgroundOptions, { activateWorkers = false, activatingTransitionalWorkstreams = false, }) {
138
168
  const defaultQueueConnection = backgroundOptions.defaultQueueConnection;
139
169
  const defaultWorkerConnection = backgroundOptions.defaultWorkerConnection;
@@ -239,6 +269,11 @@ export class Background {
239
269
  });
240
270
  }
241
271
  }
272
+ /**
273
+ * @internal
274
+ *
275
+ * connects to BullMQ using native BullMQ arguments
276
+ */
242
277
  nativeBullMQConnect(defaultBullMQQueueOptions, backgroundOptions, { activateWorkers = false, }) {
243
278
  const nativeBullMQ = backgroundOptions.nativeBullMQ;
244
279
  const defaultQueueConnection = nativeBullMQ.defaultQueueOptions?.queueConnection || backgroundOptions.defaultQueueConnection;
@@ -283,6 +318,7 @@ export class Background {
283
318
  /////////////////////////
284
319
  const namedQueueOptionsMap = nativeBullMQ.namedQueueOptions || {};
285
320
  Object.keys(namedQueueOptionsMap).forEach(queueName => {
321
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
286
322
  const namedQueueOptions = namedQueueOptionsMap[queueName];
287
323
  if (namedQueueOptions.queueConnection)
288
324
  this.redisConnections.push(namedQueueOptions.queueConnection);
@@ -305,7 +341,7 @@ export class Background {
305
341
  const extraWorkerOptions = extraWorkerOptionsMap[queueName];
306
342
  const extraWorkerCount = extraWorkerOptions ? (extraWorkerOptions.workerCount ?? 1) : 0;
307
343
  this.groupNames[queueName] ||= [];
308
- if (extraWorkerOptions.group?.id)
344
+ if (extraWorkerOptions?.group?.id)
309
345
  this.groupNames[queueName].push(extraWorkerOptions.group.id);
310
346
  if (activateWorkers) {
311
347
  if (!namedWorkerConnection)
@@ -325,16 +361,34 @@ export class Background {
325
361
  // end: create named queues //
326
362
  //////////////////////////////
327
363
  }
364
+ /**
365
+ * starts background workers
366
+ */
328
367
  work() {
329
368
  this.connect({ activateWorkers: true });
330
369
  process.on('SIGTERM', () => {
331
- void this.shutdownAndExit();
370
+ void this.shutdownAndExit()
371
+ .then(() => { })
372
+ .catch(() => { });
332
373
  });
333
374
  process.on('SIGINT', () => {
334
- void this.shutdownAndExit();
375
+ void this.shutdownAndExit()
376
+ .then(() => { })
377
+ .catch(() => { });
335
378
  });
336
379
  }
337
- async staticMethod(ObjectClass, method, { delaySeconds, globalName, args = [], jobConfig = {}, }) {
380
+ /**
381
+ * adds the static method of a provided class to BullMQ
382
+ *
383
+ * @param ObjectClass - the class you wish to background
384
+ * @param method - the method you wish to background
385
+ * @param globalName - the globalName of the class you are processing
386
+ * @param args - (optional) a list of arguments to provide to your method when it is called
387
+ * @param delaySeconds - (optional) the number of seconds you wish to wait before allowing this job to process
388
+ * @param importKey - (optional) the import key for the class
389
+ * @param jobConfig - (optional) the background job config to use when backgrounding this method
390
+ */
391
+ async staticMethod(ObjectClass, method, { globalName, delaySeconds, args = [], jobConfig = {}, }) {
338
392
  this.connect();
339
393
  await this._addToQueue(`BackgroundJobQueueStaticJob`, {
340
394
  globalName,
@@ -342,11 +396,23 @@ export class Background {
342
396
  args,
343
397
  }, {
344
398
  delaySeconds,
345
- jobConfig: jobConfig,
399
+ jobConfig,
346
400
  groupId: this.jobConfigToGroupId(jobConfig),
347
401
  priority: this.jobConfigToPriority(jobConfig),
348
402
  });
349
403
  }
404
+ /**
405
+ * adds the static method of a provided class to BullMQ,
406
+ * to be scheduled to run at a specified cron pattern
407
+ *
408
+ * @param ObjectClass - the class you wish to background
409
+ * @param pattern - the cron string you wish to use to govern the scheduling for this job
410
+ * @param method - the method you wish to background
411
+ * @param globalName - the globalName of the class you are processing
412
+ * @param args - (optional) a list of arguments to provide to your method when it is called
413
+ * @param importKey - (optional) the import key for the class
414
+ * @param jobConfig - (optional) the background job config to use when backgrounding this method
415
+ */
350
416
  async scheduledMethod(ObjectClass, pattern, method, { globalName, args = [], jobConfig = {}, }) {
351
417
  this.connect();
352
418
  // `jobId` is used to determine uniqueness along with name and repeat pattern.
@@ -356,7 +422,10 @@ export class Background {
356
422
  //
357
423
  // See: https://docs.bullmq.io/guide/jobs/repeatable
358
424
  const jobId = `${ObjectClass.name}:${method}`;
359
- await this.queueInstance(jobConfig).add('BackgroundJobQueueStaticJob', {
425
+ const queueInstance = this.queueInstance(jobConfig);
426
+ if (!queueInstance)
427
+ throw new Error(`Missing queue for: ${jobConfig.queue?.toString()}`);
428
+ await queueInstance.add('BackgroundJobQueueStaticJob', {
360
429
  globalName,
361
430
  method,
362
431
  args,
@@ -389,6 +458,16 @@ export class Background {
389
458
  }
390
459
  return queueInstance;
391
460
  }
461
+ /**
462
+ * adds the instance method of a provided dream model to BullMQ
463
+ *
464
+ * @param modelInstance - the dream model instance you wish to background
465
+ * @param method - the method you wish to background
466
+ * @param globalName - the globalName of the class you are processing
467
+ * @param args - (optional) a list of arguments to provide to your method when it is called
468
+ * @param importKey - (optional) the import key for the class
469
+ * @param jobConfig - (optional) the background job config to use when backgrounding this method
470
+ */
392
471
  async modelInstanceMethod(modelInstance, method, { delaySeconds, args = [], jobConfig = {}, }) {
393
472
  this.connect();
394
473
  await this._addToQueue('BackgroundJobQueueModelInstanceJob', {
@@ -398,7 +477,7 @@ export class Background {
398
477
  args,
399
478
  }, {
400
479
  delaySeconds,
401
- jobConfig: jobConfig,
480
+ jobConfig,
402
481
  groupId: this.jobConfigToGroupId(jobConfig),
403
482
  priority: this.jobConfigToPriority(jobConfig),
404
483
  });
@@ -413,9 +492,12 @@ export class Background {
413
492
  const queue = new Background.Queue('TestQueue', { connection: {} });
414
493
  const job = new Job(queue, jobType, jobData, {});
415
494
  await this.doWork(job);
495
+ return;
416
496
  //
417
497
  }
418
- else if (groupId && priority) {
498
+ if (!queueInstance)
499
+ throw new Error(`missing queue: ${jobConfig?.queue?.toString() || 'N/A'}`);
500
+ if (groupId && priority) {
419
501
  await queueInstance.add(jobType, jobData, {
420
502
  delay,
421
503
  group: {
@@ -516,9 +598,3 @@ export default background;
516
598
  export async function stopBackgroundWorkers() {
517
599
  await background.shutdown();
518
600
  }
519
- function nameToRedisQueueName(queueName, redis) {
520
- queueName = queueName.replace(/\{|\}/g, '');
521
- if (redis instanceof Cluster)
522
- return `{${queueName}}`;
523
- return queueName;
524
- }
@@ -0,0 +1,8 @@
1
+ export default class ActivatingBackgroundWorkersWithoutDefaultWorkerConnection extends Error {
2
+ get message() {
3
+ return `
4
+ defaultWorkerConnection is required when activating workers. For example,
5
+ it may be omitted on webserver instances, but is required on worker instances.
6
+ `;
7
+ }
8
+ }
@@ -0,0 +1,14 @@
1
+ export default class ActivatingNamedQueueBackgroundWorkersWithoutWorkerConnection extends Error {
2
+ queueName;
3
+ constructor(queueName) {
4
+ super();
5
+ this.queueName = queueName;
6
+ }
7
+ get message() {
8
+ return `
9
+ defaultWorkerConnection is missing, and the ${this.queueName} queue does not
10
+ specify a workerConnection. A worker connection isrequired when activating workers.
11
+ For example, it may be omitted on webserver instances, but is required on worker instances.
12
+ `;
13
+ }
14
+ }
@@ -0,0 +1,8 @@
1
+ export default class DefaultBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection extends Error {
2
+ get message() {
3
+ return `
4
+ Native BullMQ options don't include a default queue connection, and the
5
+ default config does not include a queue connection
6
+ `;
7
+ }
8
+ }
@@ -0,0 +1,13 @@
1
+ export default class NamedBullMQNativeOptionsMissingQueueConnectionAndDefaultQueueConnection extends Error {
2
+ queueName;
3
+ constructor(queueName) {
4
+ super();
5
+ this.queueName = queueName;
6
+ }
7
+ get message() {
8
+ return `
9
+ Native BullMQ options don't include a default queue connection, and the
10
+ ${this.queueName} queue does not include a queue connection
11
+ `;
12
+ }
13
+ }
@@ -1,4 +1,4 @@
1
- export { default as background, Background, stopBackgroundWorkers, } from './background/index.js';
1
+ export { default as background, Background, stopBackgroundWorkers } from './background/index.js';
2
2
  export { default as BaseBackgroundedModel } from './background/BaseBackgroundedModel.js';
3
3
  export { default as BaseBackgroundedService } from './background/BaseBackgroundedService.js';
4
4
  export { default as BaseScheduledService } from './background/BaseScheduledService.js';
@@ -1,6 +1,6 @@
1
1
  import { Queue, Worker } from 'bullmq';
2
- import background from '../background/index.js';
3
2
  import { cachePsychicWorkersApp, getCachedPsychicWorkersAppOrFail } from './cache.js';
3
+ import background from '../background/index.js';
4
4
  export default class PsychicAppWorkers {
5
5
  static async init(psychicApp, cb) {
6
6
  const psychicWorkersApp = new PsychicAppWorkers(psychicApp);
@@ -0,0 +1 @@
1
+ export {};