@monque/core 0.1.0 → 0.2.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.
- package/README.md +11 -2
- package/dist/{errors-BX3oWYfZ.cjs → errors-D5ZGG2uI.cjs} +4 -4
- package/dist/errors-D5ZGG2uI.cjs.map +1 -0
- package/dist/{errors-DWkXsP3R.mjs → errors-DEvnqoOC.mjs} +1 -1
- package/dist/{errors-DW20rHWR.mjs → errors-DQ2_gprw.mjs} +4 -4
- package/dist/errors-DQ2_gprw.mjs.map +1 -0
- package/dist/{errors-Ca92IlaL.cjs → errors-Dfli-u59.cjs} +1 -1
- package/dist/index.cjs +15 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -12
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +15 -12
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +15 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
- package/dist/errors-BX3oWYfZ.cjs.map +0 -1
- package/dist/errors-DW20rHWR.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -4,6 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
<h1 align="center">@monque/core</h1>
|
|
6
6
|
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/@monque/core">
|
|
9
|
+
<img src="https://img.shields.io/npm/v/%40monque%2Fcore?style=for-the-badge&label=%40monque%2Fcore" alt="@monque/core version" />
|
|
10
|
+
</a>
|
|
11
|
+
<a href="https://codecov.io/gh/ueberBrot/monque">
|
|
12
|
+
<img src="https://img.shields.io/codecov/c/github/ueberBrot/monque?style=for-the-badge&logo=codecov&logoColor=white" alt="Codecov" />
|
|
13
|
+
</a>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
7
16
|
<p align="center">MongoDB-backed job scheduler with atomic locking, exponential backoff, and cron scheduling.</p>
|
|
8
17
|
|
|
9
18
|
> [!WARNING]
|
|
@@ -42,7 +51,7 @@ const monque = new Monque(client.db('myapp'), {
|
|
|
42
51
|
await monque.initialize();
|
|
43
52
|
|
|
44
53
|
// Register workers
|
|
45
|
-
monque.
|
|
54
|
+
monque.register('send-email', async (job) => {
|
|
46
55
|
await sendEmail(job.data.to, job.data.subject);
|
|
47
56
|
});
|
|
48
57
|
|
|
@@ -81,7 +90,7 @@ Creates a new Monque instance.
|
|
|
81
90
|
- `enqueue(name, data, options?)` - Enqueue a job
|
|
82
91
|
- `now(name, data)` - Enqueue for immediate processing
|
|
83
92
|
- `schedule(cron, name, data)` - Schedule recurring job
|
|
84
|
-
- `
|
|
93
|
+
- `register(name, handler, options?)` - Register a worker
|
|
85
94
|
- `start()` - Start processing jobs
|
|
86
95
|
- `stop()` - Graceful shutdown
|
|
87
96
|
- `isHealthy()` - Check scheduler health
|
|
@@ -99,8 +99,8 @@ var ShutdownTimeoutError = class ShutdownTimeoutError extends MonqueError {
|
|
|
99
99
|
* @example
|
|
100
100
|
* ```typescript
|
|
101
101
|
* try {
|
|
102
|
-
* monque.
|
|
103
|
-
* monque.
|
|
102
|
+
* monque.register('send-email', handler1);
|
|
103
|
+
* monque.register('send-email', handler2); // throws
|
|
104
104
|
* } catch (error) {
|
|
105
105
|
* if (error instanceof WorkerRegistrationError) {
|
|
106
106
|
* console.error('Worker already registered for:', error.jobName);
|
|
@@ -108,7 +108,7 @@ var ShutdownTimeoutError = class ShutdownTimeoutError extends MonqueError {
|
|
|
108
108
|
* }
|
|
109
109
|
*
|
|
110
110
|
* // To intentionally replace a worker:
|
|
111
|
-
* monque.
|
|
111
|
+
* monque.register('send-email', handler2, { replace: true });
|
|
112
112
|
* ```
|
|
113
113
|
*/
|
|
114
114
|
var WorkerRegistrationError = class WorkerRegistrationError extends MonqueError {
|
|
@@ -152,4 +152,4 @@ Object.defineProperty(exports, 'WorkerRegistrationError', {
|
|
|
152
152
|
return WorkerRegistrationError;
|
|
153
153
|
}
|
|
154
154
|
});
|
|
155
|
-
//# sourceMappingURL=errors-
|
|
155
|
+
//# sourceMappingURL=errors-D5ZGG2uI.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-D5ZGG2uI.cjs","names":[],"sources":["../src/shared/errors.ts"],"sourcesContent":["import type { Job } from '@/jobs';\n\n/**\n * Base error class for all Monque-related errors.\n *\n * @example\n * ```typescript\n * try {\n * await monque.enqueue('job', data);\n * } catch (error) {\n * if (error instanceof MonqueError) {\n * console.error('Monque error:', error.message);\n * }\n * }\n * ```\n */\nexport class MonqueError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'MonqueError';\n\t\t// Maintains proper stack trace for where our error was thrown (only available on V8)\n\t\t/* istanbul ignore next -- @preserve captureStackTrace is always available in Node.js */\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, MonqueError);\n\t\t}\n\t}\n}\n\n/**\n * Error thrown when an invalid cron expression is provided.\n *\n * @example\n * ```typescript\n * try {\n * await monque.schedule('invalid cron', 'job', data);\n * } catch (error) {\n * if (error instanceof InvalidCronError) {\n * console.error('Invalid expression:', error.expression);\n * }\n * }\n * ```\n */\nexport class InvalidCronError extends MonqueError {\n\tconstructor(\n\t\tpublic readonly expression: string,\n\t\tmessage: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'InvalidCronError';\n\t\t/* istanbul ignore next -- @preserve captureStackTrace is always available in Node.js */\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, InvalidCronError);\n\t\t}\n\t}\n}\n\n/**\n * Error thrown when there's a database connection issue.\n *\n * @example\n * ```typescript\n * try {\n * await monque.enqueue('job', data);\n * } catch (error) {\n * if (error instanceof ConnectionError) {\n * console.error('Database connection lost');\n * }\n * }\n * ```\n */\nexport class ConnectionError extends MonqueError {\n\tconstructor(message: string, options?: { cause?: Error }) {\n\t\tsuper(message);\n\t\tthis.name = 'ConnectionError';\n\t\tif (options?.cause) {\n\t\t\tthis.cause = options.cause;\n\t\t}\n\t\t/* istanbul ignore next -- @preserve captureStackTrace is always available in Node.js */\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, ConnectionError);\n\t\t}\n\t}\n}\n\n/**\n * Error thrown when graceful shutdown times out.\n * Includes information about jobs that were still in progress.\n *\n * @example\n * ```typescript\n * try {\n * await monque.stop();\n * } catch (error) {\n * if (error instanceof ShutdownTimeoutError) {\n * console.error('Incomplete jobs:', error.incompleteJobs.length);\n * }\n * }\n * ```\n */\nexport class ShutdownTimeoutError extends MonqueError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly incompleteJobs: Job[],\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'ShutdownTimeoutError';\n\t\t/* istanbul ignore next -- @preserve captureStackTrace is always available in Node.js */\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, ShutdownTimeoutError);\n\t\t}\n\t}\n}\n\n/**\n * Error thrown when attempting to register a worker for a job name\n * that already has a registered worker, without explicitly allowing replacement.\n *\n * @example\n * ```typescript\n * try {\n * monque.register('send-email', handler1);\n * monque.register('send-email', handler2); // throws\n * } catch (error) {\n * if (error instanceof WorkerRegistrationError) {\n * console.error('Worker already registered for:', error.jobName);\n * }\n * }\n *\n * // To intentionally replace a worker:\n * monque.register('send-email', handler2, { replace: true });\n * ```\n */\nexport class WorkerRegistrationError extends MonqueError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly jobName: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'WorkerRegistrationError';\n\t\t/* istanbul ignore next -- @preserve captureStackTrace is always available in Node.js */\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, WorkerRegistrationError);\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,IAAa,cAAb,MAAa,oBAAoB,MAAM;CACtC,YAAY,SAAiB;AAC5B,QAAM,QAAQ;AACd,OAAK,OAAO;;AAGZ,MAAI,MAAM,kBACT,OAAM,kBAAkB,MAAM,YAAY;;;;;;;;;;;;;;;;;AAmB7C,IAAa,mBAAb,MAAa,yBAAyB,YAAY;CACjD,YACC,AAAgB,YAChB,SACC;AACD,QAAM,QAAQ;EAHE;AAIhB,OAAK,OAAO;;AAEZ,MAAI,MAAM,kBACT,OAAM,kBAAkB,MAAM,iBAAiB;;;;;;;;;;;;;;;;;AAmBlD,IAAa,kBAAb,MAAa,wBAAwB,YAAY;CAChD,YAAY,SAAiB,SAA6B;AACzD,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,MAAI,SAAS,MACZ,MAAK,QAAQ,QAAQ;;AAGtB,MAAI,MAAM,kBACT,OAAM,kBAAkB,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;AAoBjD,IAAa,uBAAb,MAAa,6BAA6B,YAAY;CACrD,YACC,SACA,AAAgB,gBACf;AACD,QAAM,QAAQ;EAFE;AAGhB,OAAK,OAAO;;AAEZ,MAAI,MAAM,kBACT,OAAM,kBAAkB,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;AAwBtD,IAAa,0BAAb,MAAa,gCAAgC,YAAY;CACxD,YACC,SACA,AAAgB,SACf;AACD,QAAM,QAAQ;EAFE;AAGhB,OAAK,OAAO;;AAEZ,MAAI,MAAM,kBACT,OAAM,kBAAkB,MAAM,wBAAwB"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as WorkerRegistrationError, i as ShutdownTimeoutError, n as InvalidCronError, r as MonqueError, t as ConnectionError } from "./errors-
|
|
1
|
+
import { a as WorkerRegistrationError, i as ShutdownTimeoutError, n as InvalidCronError, r as MonqueError, t as ConnectionError } from "./errors-DQ2_gprw.mjs";
|
|
2
2
|
|
|
3
3
|
export { ShutdownTimeoutError };
|
|
@@ -98,8 +98,8 @@ var ShutdownTimeoutError = class ShutdownTimeoutError extends MonqueError {
|
|
|
98
98
|
* @example
|
|
99
99
|
* ```typescript
|
|
100
100
|
* try {
|
|
101
|
-
* monque.
|
|
102
|
-
* monque.
|
|
101
|
+
* monque.register('send-email', handler1);
|
|
102
|
+
* monque.register('send-email', handler2); // throws
|
|
103
103
|
* } catch (error) {
|
|
104
104
|
* if (error instanceof WorkerRegistrationError) {
|
|
105
105
|
* console.error('Worker already registered for:', error.jobName);
|
|
@@ -107,7 +107,7 @@ var ShutdownTimeoutError = class ShutdownTimeoutError extends MonqueError {
|
|
|
107
107
|
* }
|
|
108
108
|
*
|
|
109
109
|
* // To intentionally replace a worker:
|
|
110
|
-
* monque.
|
|
110
|
+
* monque.register('send-email', handler2, { replace: true });
|
|
111
111
|
* ```
|
|
112
112
|
*/
|
|
113
113
|
var WorkerRegistrationError = class WorkerRegistrationError extends MonqueError {
|
|
@@ -122,4 +122,4 @@ var WorkerRegistrationError = class WorkerRegistrationError extends MonqueError
|
|
|
122
122
|
|
|
123
123
|
//#endregion
|
|
124
124
|
export { WorkerRegistrationError as a, ShutdownTimeoutError as i, InvalidCronError as n, MonqueError as r, ConnectionError as t };
|
|
125
|
-
//# sourceMappingURL=errors-
|
|
125
|
+
//# sourceMappingURL=errors-DQ2_gprw.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-DQ2_gprw.mjs","names":[],"sources":["../src/shared/errors.ts"],"sourcesContent":["import type { Job } from '@/jobs';\n\n/**\n * Base error class for all Monque-related errors.\n *\n * @example\n * ```typescript\n * try {\n * await monque.enqueue('job', data);\n * } catch (error) {\n * if (error instanceof MonqueError) {\n * console.error('Monque error:', error.message);\n * }\n * }\n * ```\n */\nexport class MonqueError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'MonqueError';\n\t\t// Maintains proper stack trace for where our error was thrown (only available on V8)\n\t\t/* istanbul ignore next -- @preserve captureStackTrace is always available in Node.js */\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, MonqueError);\n\t\t}\n\t}\n}\n\n/**\n * Error thrown when an invalid cron expression is provided.\n *\n * @example\n * ```typescript\n * try {\n * await monque.schedule('invalid cron', 'job', data);\n * } catch (error) {\n * if (error instanceof InvalidCronError) {\n * console.error('Invalid expression:', error.expression);\n * }\n * }\n * ```\n */\nexport class InvalidCronError extends MonqueError {\n\tconstructor(\n\t\tpublic readonly expression: string,\n\t\tmessage: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'InvalidCronError';\n\t\t/* istanbul ignore next -- @preserve captureStackTrace is always available in Node.js */\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, InvalidCronError);\n\t\t}\n\t}\n}\n\n/**\n * Error thrown when there's a database connection issue.\n *\n * @example\n * ```typescript\n * try {\n * await monque.enqueue('job', data);\n * } catch (error) {\n * if (error instanceof ConnectionError) {\n * console.error('Database connection lost');\n * }\n * }\n * ```\n */\nexport class ConnectionError extends MonqueError {\n\tconstructor(message: string, options?: { cause?: Error }) {\n\t\tsuper(message);\n\t\tthis.name = 'ConnectionError';\n\t\tif (options?.cause) {\n\t\t\tthis.cause = options.cause;\n\t\t}\n\t\t/* istanbul ignore next -- @preserve captureStackTrace is always available in Node.js */\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, ConnectionError);\n\t\t}\n\t}\n}\n\n/**\n * Error thrown when graceful shutdown times out.\n * Includes information about jobs that were still in progress.\n *\n * @example\n * ```typescript\n * try {\n * await monque.stop();\n * } catch (error) {\n * if (error instanceof ShutdownTimeoutError) {\n * console.error('Incomplete jobs:', error.incompleteJobs.length);\n * }\n * }\n * ```\n */\nexport class ShutdownTimeoutError extends MonqueError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly incompleteJobs: Job[],\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'ShutdownTimeoutError';\n\t\t/* istanbul ignore next -- @preserve captureStackTrace is always available in Node.js */\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, ShutdownTimeoutError);\n\t\t}\n\t}\n}\n\n/**\n * Error thrown when attempting to register a worker for a job name\n * that already has a registered worker, without explicitly allowing replacement.\n *\n * @example\n * ```typescript\n * try {\n * monque.register('send-email', handler1);\n * monque.register('send-email', handler2); // throws\n * } catch (error) {\n * if (error instanceof WorkerRegistrationError) {\n * console.error('Worker already registered for:', error.jobName);\n * }\n * }\n *\n * // To intentionally replace a worker:\n * monque.register('send-email', handler2, { replace: true });\n * ```\n */\nexport class WorkerRegistrationError extends MonqueError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly jobName: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'WorkerRegistrationError';\n\t\t/* istanbul ignore next -- @preserve captureStackTrace is always available in Node.js */\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, WorkerRegistrationError);\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,IAAa,cAAb,MAAa,oBAAoB,MAAM;CACtC,YAAY,SAAiB;AAC5B,QAAM,QAAQ;AACd,OAAK,OAAO;;AAGZ,MAAI,MAAM,kBACT,OAAM,kBAAkB,MAAM,YAAY;;;;;;;;;;;;;;;;;AAmB7C,IAAa,mBAAb,MAAa,yBAAyB,YAAY;CACjD,YACC,AAAgB,YAChB,SACC;AACD,QAAM,QAAQ;EAHE;AAIhB,OAAK,OAAO;;AAEZ,MAAI,MAAM,kBACT,OAAM,kBAAkB,MAAM,iBAAiB;;;;;;;;;;;;;;;;;AAmBlD,IAAa,kBAAb,MAAa,wBAAwB,YAAY;CAChD,YAAY,SAAiB,SAA6B;AACzD,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,MAAI,SAAS,MACZ,MAAK,QAAQ,QAAQ;;AAGtB,MAAI,MAAM,kBACT,OAAM,kBAAkB,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;AAoBjD,IAAa,uBAAb,MAAa,6BAA6B,YAAY;CACrD,YACC,SACA,AAAgB,gBACf;AACD,QAAM,QAAQ;EAFE;AAGhB,OAAK,OAAO;;AAEZ,MAAI,MAAM,kBACT,OAAM,kBAAkB,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;AAwBtD,IAAa,0BAAb,MAAa,gCAAgC,YAAY;CACxD,YACC,SACA,AAAgB,SACf;AACD,QAAM,QAAQ;EAFE;AAGhB,OAAK,OAAO;;AAEZ,MAAI,MAAM,kBACT,OAAM,kBAAkB,MAAM,wBAAwB"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_errors = require('./errors-
|
|
1
|
+
const require_errors = require('./errors-D5ZGG2uI.cjs');
|
|
2
2
|
let node_crypto = require("node:crypto");
|
|
3
3
|
let node_events = require("node:events");
|
|
4
4
|
let cron_parser = require("cron-parser");
|
|
@@ -396,7 +396,7 @@ type EmailJob = {};
|
|
|
396
396
|
* body: string
|
|
397
397
|
* }
|
|
398
398
|
*
|
|
399
|
-
* monque.
|
|
399
|
+
* monque.register<EmailJob>('send-email', async (job) =>
|
|
400
400
|
{
|
|
401
401
|
* await emailService.send(job.data.to, job.data.subject, job.data.body)
|
|
402
402
|
*
|
|
@@ -845,7 +845,7 @@ var Monque = class extends node_events.EventEmitter {
|
|
|
845
845
|
* body: string;
|
|
846
846
|
* }
|
|
847
847
|
*
|
|
848
|
-
* monque.
|
|
848
|
+
* monque.register<EmailJob>('send-email', async (job) => {
|
|
849
849
|
* await emailService.send(job.data.to, job.data.subject, job.data.body);
|
|
850
850
|
* });
|
|
851
851
|
* ```
|
|
@@ -853,7 +853,7 @@ var Monque = class extends node_events.EventEmitter {
|
|
|
853
853
|
* @example Worker with custom concurrency
|
|
854
854
|
* ```typescript
|
|
855
855
|
* // Limit to 2 concurrent video processing jobs (resource-intensive)
|
|
856
|
-
* monque.
|
|
856
|
+
* monque.register('process-video', async (job) => {
|
|
857
857
|
* await videoProcessor.transcode(job.data.videoId);
|
|
858
858
|
* }, { concurrency: 2 });
|
|
859
859
|
* ```
|
|
@@ -861,12 +861,12 @@ var Monque = class extends node_events.EventEmitter {
|
|
|
861
861
|
* @example Replacing an existing worker
|
|
862
862
|
* ```typescript
|
|
863
863
|
* // Replace the existing handler for 'send-email'
|
|
864
|
-
* monque.
|
|
864
|
+
* monque.register('send-email', newEmailHandler, { replace: true });
|
|
865
865
|
* ```
|
|
866
866
|
*
|
|
867
867
|
* @example Worker with error handling
|
|
868
868
|
* ```typescript
|
|
869
|
-
* monque.
|
|
869
|
+
* monque.register('sync-user', async (job) => {
|
|
870
870
|
* try {
|
|
871
871
|
* await externalApi.syncUser(job.data.userId);
|
|
872
872
|
* } catch (error) {
|
|
@@ -877,7 +877,7 @@ var Monque = class extends node_events.EventEmitter {
|
|
|
877
877
|
* });
|
|
878
878
|
* ```
|
|
879
879
|
*/
|
|
880
|
-
|
|
880
|
+
register(name, handler, options = {}) {
|
|
881
881
|
const concurrency = options.concurrency ?? this.options.defaultConcurrency;
|
|
882
882
|
if (this.workers.has(name) && options.replace !== true) throw new require_errors.WorkerRegistrationError(`Worker already registered for job name "${name}". Use { replace: true } to replace.`, name);
|
|
883
883
|
this.workers.set(name, {
|
|
@@ -901,8 +901,8 @@ var Monque = class extends node_events.EventEmitter {
|
|
|
901
901
|
* const monque = new Monque(db);
|
|
902
902
|
* await monque.initialize();
|
|
903
903
|
*
|
|
904
|
-
* monque.
|
|
905
|
-
* monque.
|
|
904
|
+
* monque.register('send-email', emailHandler);
|
|
905
|
+
* monque.register('process-order', orderHandler);
|
|
906
906
|
*
|
|
907
907
|
* monque.start(); // Begin processing jobs
|
|
908
908
|
* ```
|
|
@@ -1037,7 +1037,7 @@ var Monque = class extends node_events.EventEmitter {
|
|
|
1037
1037
|
}
|
|
1038
1038
|
if (result === "timeout") {
|
|
1039
1039
|
const incompleteJobs = this.getActiveJobsList();
|
|
1040
|
-
const { ShutdownTimeoutError: ShutdownTimeoutError$1 } = await Promise.resolve().then(() => require("./errors-
|
|
1040
|
+
const { ShutdownTimeoutError: ShutdownTimeoutError$1 } = await Promise.resolve().then(() => require("./errors-Dfli-u59.cjs"));
|
|
1041
1041
|
const error = new ShutdownTimeoutError$1(`Shutdown timed out after ${this.options.shutdownTimeout}ms with ${incompleteJobs.length} incomplete jobs`, incompleteJobs);
|
|
1042
1042
|
this.emit("job:error", { error });
|
|
1043
1043
|
}
|
|
@@ -1195,6 +1195,7 @@ var Monque = class extends node_events.EventEmitter {
|
|
|
1195
1195
|
*
|
|
1196
1196
|
* Called at regular intervals (configured by `pollInterval`). For each registered worker,
|
|
1197
1197
|
* attempts to acquire jobs up to the worker's available concurrency slots.
|
|
1198
|
+
* Aborts early if the scheduler is stopping (`isRunning` is false).
|
|
1198
1199
|
*
|
|
1199
1200
|
* @private
|
|
1200
1201
|
*/
|
|
@@ -1204,6 +1205,7 @@ var Monque = class extends node_events.EventEmitter {
|
|
|
1204
1205
|
const availableSlots = worker.concurrency - worker.activeJobs.size;
|
|
1205
1206
|
if (availableSlots <= 0) continue;
|
|
1206
1207
|
for (let i = 0; i < availableSlots; i++) {
|
|
1208
|
+
if (!this.isRunning) return;
|
|
1207
1209
|
const job = await this.acquireJob(name);
|
|
1208
1210
|
if (job) this.processJob(job, worker).catch((error) => {
|
|
1209
1211
|
this.emit("job:error", {
|
|
@@ -1224,12 +1226,14 @@ var Monque = class extends node_events.EventEmitter {
|
|
|
1224
1226
|
* - Has nextRunAt <= now
|
|
1225
1227
|
* - Is not claimed by another instance (claimedBy is null/undefined)
|
|
1226
1228
|
*
|
|
1229
|
+
* Returns `null` immediately if scheduler is stopping (`isRunning` is false).
|
|
1230
|
+
*
|
|
1227
1231
|
* @private
|
|
1228
1232
|
* @param name - The job type to acquire
|
|
1229
1233
|
* @returns The acquired job with updated status, claimedBy, and heartbeat info, or `null` if no jobs available
|
|
1230
1234
|
*/
|
|
1231
1235
|
async acquireJob(name) {
|
|
1232
|
-
if (!this.collection) return null;
|
|
1236
|
+
if (!this.collection || !this.isRunning) return null;
|
|
1233
1237
|
const now = /* @__PURE__ */ new Date();
|
|
1234
1238
|
const result = await this.collection.findOneAndUpdate({
|
|
1235
1239
|
name,
|