@quave/agenda 1.0.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/LICENSE.md +25 -0
- package/README.md +380 -0
- package/dist/Job.d.ts +190 -0
- package/dist/Job.js +689 -0
- package/dist/Job.js.map +1 -0
- package/dist/JobProcessingQueue.d.ts +47 -0
- package/dist/JobProcessingQueue.js +107 -0
- package/dist/JobProcessingQueue.js.map +1 -0
- package/dist/JobProcessor.d.ts +72 -0
- package/dist/JobProcessor.js +512 -0
- package/dist/JobProcessor.js.map +1 -0
- package/dist/backends/index.d.ts +18 -0
- package/dist/backends/index.js +20 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/cjs/Job.d.ts +190 -0
- package/dist/cjs/Job.js +696 -0
- package/dist/cjs/Job.js.map +1 -0
- package/dist/cjs/JobProcessingQueue.d.ts +47 -0
- package/dist/cjs/JobProcessingQueue.js +111 -0
- package/dist/cjs/JobProcessingQueue.js.map +1 -0
- package/dist/cjs/JobProcessor.d.ts +72 -0
- package/dist/cjs/JobProcessor.js +519 -0
- package/dist/cjs/JobProcessor.js.map +1 -0
- package/dist/cjs/backends/index.d.ts +17 -0
- package/dist/cjs/backends/index.js +20 -0
- package/dist/cjs/backends/index.js.map +1 -0
- package/dist/cjs/decorators/Define.d.ts +33 -0
- package/dist/cjs/decorators/Define.js +47 -0
- package/dist/cjs/decorators/Define.js.map +1 -0
- package/dist/cjs/decorators/Every.d.ts +43 -0
- package/dist/cjs/decorators/Every.js +58 -0
- package/dist/cjs/decorators/Every.js.map +1 -0
- package/dist/cjs/decorators/JobsController.d.ts +43 -0
- package/dist/cjs/decorators/JobsController.js +40 -0
- package/dist/cjs/decorators/JobsController.js.map +1 -0
- package/dist/cjs/decorators/index.d.ts +41 -0
- package/dist/cjs/decorators/index.js +57 -0
- package/dist/cjs/decorators/index.js.map +1 -0
- package/dist/cjs/decorators/metadata.d.ts +50 -0
- package/dist/cjs/decorators/metadata.js +41 -0
- package/dist/cjs/decorators/metadata.js.map +1 -0
- package/dist/cjs/decorators/register.d.ts +52 -0
- package/dist/cjs/decorators/register.js +145 -0
- package/dist/cjs/decorators/register.js.map +1 -0
- package/dist/cjs/index.d.ts +498 -0
- package/dist/cjs/index.js +776 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/notifications/BaseNotificationChannel.d.ts +47 -0
- package/dist/cjs/notifications/BaseNotificationChannel.js +112 -0
- package/dist/cjs/notifications/BaseNotificationChannel.js.map +1 -0
- package/dist/cjs/notifications/InMemoryNotificationChannel.d.ts +13 -0
- package/dist/cjs/notifications/InMemoryNotificationChannel.js +37 -0
- package/dist/cjs/notifications/InMemoryNotificationChannel.js.map +1 -0
- package/dist/cjs/notifications/index.d.ts +2 -0
- package/dist/cjs/notifications/index.js +8 -0
- package/dist/cjs/notifications/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/types/AgendaBackend.d.ts +61 -0
- package/dist/cjs/types/AgendaBackend.js +3 -0
- package/dist/cjs/types/AgendaBackend.js.map +1 -0
- package/dist/cjs/types/AgendaConfig.d.ts +10 -0
- package/dist/cjs/types/AgendaConfig.js +3 -0
- package/dist/cjs/types/AgendaConfig.js.map +1 -0
- package/dist/cjs/types/AgendaStatus.d.ts +32 -0
- package/dist/cjs/types/AgendaStatus.js +3 -0
- package/dist/cjs/types/AgendaStatus.js.map +1 -0
- package/dist/cjs/types/DbOptions.d.ts +4 -0
- package/dist/cjs/types/DbOptions.js +3 -0
- package/dist/cjs/types/DbOptions.js.map +1 -0
- package/dist/cjs/types/DrainOptions.d.ts +37 -0
- package/dist/cjs/types/DrainOptions.js +3 -0
- package/dist/cjs/types/DrainOptions.js.map +1 -0
- package/dist/cjs/types/JobDefinition.d.ts +49 -0
- package/dist/cjs/types/JobDefinition.js +3 -0
- package/dist/cjs/types/JobDefinition.js.map +1 -0
- package/dist/cjs/types/JobLogger.d.ts +111 -0
- package/dist/cjs/types/JobLogger.js +3 -0
- package/dist/cjs/types/JobLogger.js.map +1 -0
- package/dist/cjs/types/JobParameters.d.ts +106 -0
- package/dist/cjs/types/JobParameters.js +21 -0
- package/dist/cjs/types/JobParameters.js.map +1 -0
- package/dist/cjs/types/JobQuery.d.ts +79 -0
- package/dist/cjs/types/JobQuery.js +36 -0
- package/dist/cjs/types/JobQuery.js.map +1 -0
- package/dist/cjs/types/JobRepository.d.ts +101 -0
- package/dist/cjs/types/JobRepository.js +3 -0
- package/dist/cjs/types/JobRepository.js.map +1 -0
- package/dist/cjs/types/NotificationChannel.d.ts +120 -0
- package/dist/cjs/types/NotificationChannel.js +3 -0
- package/dist/cjs/types/NotificationChannel.js.map +1 -0
- package/dist/cjs/utils/backoff.d.ts +152 -0
- package/dist/cjs/utils/backoff.js +175 -0
- package/dist/cjs/utils/backoff.js.map +1 -0
- package/dist/cjs/utils/dateConstraints.d.ts +48 -0
- package/dist/cjs/utils/dateConstraints.js +127 -0
- package/dist/cjs/utils/dateConstraints.js.map +1 -0
- package/dist/cjs/utils/isValidDate.d.ts +1 -0
- package/dist/cjs/utils/isValidDate.js +8 -0
- package/dist/cjs/utils/isValidDate.js.map +1 -0
- package/dist/cjs/utils/nextRunAt.d.ts +10 -0
- package/dist/cjs/utils/nextRunAt.js +119 -0
- package/dist/cjs/utils/nextRunAt.js.map +1 -0
- package/dist/cjs/utils/priority.d.ts +13 -0
- package/dist/cjs/utils/priority.js +23 -0
- package/dist/cjs/utils/priority.js.map +1 -0
- package/dist/cjs/utils/processEvery.d.ts +1 -0
- package/dist/cjs/utils/processEvery.js +13 -0
- package/dist/cjs/utils/processEvery.js.map +1 -0
- package/dist/cjs/utils/stack.d.ts +1 -0
- package/dist/cjs/utils/stack.js +21 -0
- package/dist/cjs/utils/stack.js.map +1 -0
- package/dist/cjs/version.d.ts +9 -0
- package/dist/cjs/version.js +13 -0
- package/dist/cjs/version.js.map +1 -0
- package/dist/decorators/Define.d.ts +33 -0
- package/dist/decorators/Define.js +44 -0
- package/dist/decorators/Define.js.map +1 -0
- package/dist/decorators/Every.d.ts +43 -0
- package/dist/decorators/Every.js +55 -0
- package/dist/decorators/Every.js.map +1 -0
- package/dist/decorators/JobsController.d.ts +43 -0
- package/dist/decorators/JobsController.js +37 -0
- package/dist/decorators/JobsController.js.map +1 -0
- package/dist/decorators/index.d.ts +41 -0
- package/dist/decorators/index.js +46 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/metadata.d.ts +50 -0
- package/dist/decorators/metadata.js +35 -0
- package/dist/decorators/metadata.js.map +1 -0
- package/dist/decorators/register.d.ts +52 -0
- package/dist/decorators/register.js +139 -0
- package/dist/decorators/register.js.map +1 -0
- package/dist/index.d.ts +498 -0
- package/dist/index.js +744 -0
- package/dist/index.js.map +1 -0
- package/dist/notifications/BaseNotificationChannel.d.ts +47 -0
- package/dist/notifications/BaseNotificationChannel.js +108 -0
- package/dist/notifications/BaseNotificationChannel.js.map +1 -0
- package/dist/notifications/InMemoryNotificationChannel.d.ts +13 -0
- package/dist/notifications/InMemoryNotificationChannel.js +33 -0
- package/dist/notifications/InMemoryNotificationChannel.js.map +1 -0
- package/dist/notifications/index.d.ts +2 -0
- package/dist/notifications/index.js +3 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/types/AgendaBackend.d.ts +61 -0
- package/dist/types/AgendaBackend.js +2 -0
- package/dist/types/AgendaBackend.js.map +1 -0
- package/dist/types/AgendaConfig.d.ts +10 -0
- package/dist/types/AgendaConfig.js +2 -0
- package/dist/types/AgendaConfig.js.map +1 -0
- package/dist/types/AgendaStatus.d.ts +32 -0
- package/dist/types/AgendaStatus.js +2 -0
- package/dist/types/AgendaStatus.js.map +1 -0
- package/dist/types/DbOptions.d.ts +4 -0
- package/dist/types/DbOptions.js +2 -0
- package/dist/types/DbOptions.js.map +1 -0
- package/dist/types/DrainOptions.d.ts +37 -0
- package/dist/types/DrainOptions.js +2 -0
- package/dist/types/DrainOptions.js.map +1 -0
- package/dist/types/JobDefinition.d.ts +49 -0
- package/dist/types/JobDefinition.js +2 -0
- package/dist/types/JobDefinition.js.map +1 -0
- package/dist/types/JobLogger.d.ts +111 -0
- package/dist/types/JobLogger.js +2 -0
- package/dist/types/JobLogger.js.map +1 -0
- package/dist/types/JobParameters.d.ts +106 -0
- package/dist/types/JobParameters.js +17 -0
- package/dist/types/JobParameters.js.map +1 -0
- package/dist/types/JobQuery.d.ts +79 -0
- package/dist/types/JobQuery.js +33 -0
- package/dist/types/JobQuery.js.map +1 -0
- package/dist/types/JobRepository.d.ts +101 -0
- package/dist/types/JobRepository.js +2 -0
- package/dist/types/JobRepository.js.map +1 -0
- package/dist/types/NotificationChannel.d.ts +120 -0
- package/dist/types/NotificationChannel.js +2 -0
- package/dist/types/NotificationChannel.js.map +1 -0
- package/dist/utils/backoff.d.ts +152 -0
- package/dist/utils/backoff.js +167 -0
- package/dist/utils/backoff.js.map +1 -0
- package/dist/utils/dateConstraints.d.ts +48 -0
- package/dist/utils/dateConstraints.js +117 -0
- package/dist/utils/dateConstraints.js.map +1 -0
- package/dist/utils/isValidDate.d.ts +1 -0
- package/dist/utils/isValidDate.js +5 -0
- package/dist/utils/isValidDate.js.map +1 -0
- package/dist/utils/nextRunAt.d.ts +10 -0
- package/dist/utils/nextRunAt.js +110 -0
- package/dist/utils/nextRunAt.js.map +1 -0
- package/dist/utils/priority.d.ts +13 -0
- package/dist/utils/priority.js +20 -0
- package/dist/utils/priority.js.map +1 -0
- package/dist/utils/processEvery.d.ts +1 -0
- package/dist/utils/processEvery.js +7 -0
- package/dist/utils/processEvery.js.map +1 -0
- package/dist/utils/stack.d.ts +1 -0
- package/dist/utils/stack.js +18 -0
- package/dist/utils/stack.js.map +1 -0
- package/dist/version.d.ts +9 -0
- package/dist/version.js +10 -0
- package/dist/version.js.map +1 -0
- package/package.json +79 -0
- package/test/fixtures/forkHelper.js +40 -0
- package/test/fixtures/someJobDefinition.ts +12 -0
- package/test/shared/agenda-test-suite.ts +1876 -0
- package/test/shared/backoff-test-suite.ts +408 -0
- package/test/shared/debounce-test-suite.ts +377 -0
- package/test/shared/full-test-suite.ts +161 -0
- package/test/shared/index.ts +50 -0
- package/test/shared/joblogger-test-suite.ts +305 -0
- package/test/shared/jobprocessor-test-suite.ts +266 -0
- package/test/shared/notification-channel-test-suite.ts +471 -0
- package/test/shared/removeoncomplete-test-suite.ts +228 -0
- package/test/shared/repository-test-suite.ts +708 -0
- package/test/shared/retry-test-suite.ts +174 -0
- package/test/shared/test-utils.ts +100 -0
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
import debug from 'debug';
|
|
2
|
+
import { agendaVersion } from './version.js';
|
|
3
|
+
import { Job } from './Job.js';
|
|
4
|
+
import { JobProcessingQueue } from './JobProcessingQueue.js';
|
|
5
|
+
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
6
|
+
const log = debug('agenda:jobProcessor');
|
|
7
|
+
const MAX_SAFE_32BIT_INTEGER = 2 ** 31; // Math.pow(2,31);
|
|
8
|
+
/**
|
|
9
|
+
* @class
|
|
10
|
+
* Process methods for jobs
|
|
11
|
+
*/
|
|
12
|
+
export class JobProcessor {
|
|
13
|
+
async getStatus(fullDetails = false) {
|
|
14
|
+
const jobStatus = Object.keys(this.jobStatus).reduce((obj, key) => {
|
|
15
|
+
const status = this.jobStatus[key];
|
|
16
|
+
obj[key] = {
|
|
17
|
+
running: status?.running ?? 0,
|
|
18
|
+
locked: status?.locked ?? 0,
|
|
19
|
+
config: this.agenda.definitions[key]
|
|
20
|
+
};
|
|
21
|
+
return obj;
|
|
22
|
+
}, {});
|
|
23
|
+
return {
|
|
24
|
+
version: agendaVersion,
|
|
25
|
+
queueName: this.agenda.attrs.name,
|
|
26
|
+
totalQueueSizeDB: await this.agenda.db.getQueueSize(),
|
|
27
|
+
config: {
|
|
28
|
+
totalLockLimit: this.totalLockLimit,
|
|
29
|
+
maxConcurrency: this.maxConcurrency,
|
|
30
|
+
processEvery: this.processEvery
|
|
31
|
+
},
|
|
32
|
+
backend: {
|
|
33
|
+
// Placeholder - will be overwritten by Agenda.getRunningStats()
|
|
34
|
+
name: 'unknown',
|
|
35
|
+
hasNotificationChannel: false
|
|
36
|
+
},
|
|
37
|
+
internal: {
|
|
38
|
+
localQueueProcessing: this.localQueueProcessing
|
|
39
|
+
},
|
|
40
|
+
jobStatus,
|
|
41
|
+
queuedJobs: !fullDetails
|
|
42
|
+
? this.jobQueue.length
|
|
43
|
+
: this.jobQueue.getQueue().map(job => ({
|
|
44
|
+
...job.toJson(),
|
|
45
|
+
canceled: job.getCanceledMessage()
|
|
46
|
+
})),
|
|
47
|
+
runningJobs: !fullDetails
|
|
48
|
+
? this.runningJobs.length
|
|
49
|
+
: this.runningJobs.map(job => ({
|
|
50
|
+
...job.toJson(),
|
|
51
|
+
canceled: job.getCanceledMessage()
|
|
52
|
+
})),
|
|
53
|
+
lockedJobs: !fullDetails
|
|
54
|
+
? this.lockedJobs.length
|
|
55
|
+
: this.lockedJobs.map(job => ({
|
|
56
|
+
...job.toJson(),
|
|
57
|
+
canceled: job.getCanceledMessage()
|
|
58
|
+
}))
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
constructor(agenda, maxConcurrency, totalLockLimit, processEvery, notificationChannel) {
|
|
62
|
+
this.agenda = agenda;
|
|
63
|
+
this.maxConcurrency = maxConcurrency;
|
|
64
|
+
this.totalLockLimit = totalLockLimit;
|
|
65
|
+
this.processEvery = processEvery;
|
|
66
|
+
this.jobStatus = {};
|
|
67
|
+
this.localQueueProcessing = 0;
|
|
68
|
+
this.nextScanAt = new Date();
|
|
69
|
+
this.runningJobs = [];
|
|
70
|
+
this.lockedJobs = [];
|
|
71
|
+
this.isJobQueueFilling = new Map();
|
|
72
|
+
this.isRunning = true;
|
|
73
|
+
this.notificationChannel = notificationChannel;
|
|
74
|
+
this.jobQueue = new JobProcessingQueue(this.agenda);
|
|
75
|
+
log('creating interval to call processJobs every [%dms]', processEvery);
|
|
76
|
+
this.processInterval = setInterval(() => this.process(), processEvery);
|
|
77
|
+
this.process();
|
|
78
|
+
// Subscribe to job notifications for real-time processing
|
|
79
|
+
if (this.notificationChannel) {
|
|
80
|
+
log('subscribing to notification channel');
|
|
81
|
+
this.notificationUnsubscribe = this.notificationChannel.subscribe(this.handleNotification.bind(this));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
stop() {
|
|
85
|
+
log.extend('stop')('stop job processor', this.isRunning);
|
|
86
|
+
this.isRunning = false;
|
|
87
|
+
if (this.processInterval) {
|
|
88
|
+
clearInterval(this.processInterval);
|
|
89
|
+
this.processInterval = undefined;
|
|
90
|
+
}
|
|
91
|
+
// Unsubscribe from notifications
|
|
92
|
+
if (this.notificationUnsubscribe) {
|
|
93
|
+
log.extend('stop')('unsubscribing from notification channel');
|
|
94
|
+
this.notificationUnsubscribe();
|
|
95
|
+
this.notificationUnsubscribe = undefined;
|
|
96
|
+
}
|
|
97
|
+
// Return both locked and running jobs so they can all be unlocked
|
|
98
|
+
// Running jobs are also "locked" in the database (they have lockedAt set),
|
|
99
|
+
// they just moved from lockedJobs to runningJobs when processing started
|
|
100
|
+
return [...this.lockedJobs, ...this.runningJobs];
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Waits for all currently running jobs to finish, then stops the processor.
|
|
104
|
+
* Unlike stop(), this method does not immediately return - it waits for graceful completion.
|
|
105
|
+
* @param options - Optional timeout or AbortSignal, or timeout number directly
|
|
106
|
+
* @returns Promise that resolves with drain result when complete, timed out, or aborted
|
|
107
|
+
*/
|
|
108
|
+
async drain(options) {
|
|
109
|
+
log.extend('drain')('drain called, clearing interval for processJobs()');
|
|
110
|
+
// Normalize options
|
|
111
|
+
const opts = typeof options === 'number' ? { timeout: options } : options ?? {};
|
|
112
|
+
// Stop accepting new jobs
|
|
113
|
+
if (this.processInterval) {
|
|
114
|
+
clearInterval(this.processInterval);
|
|
115
|
+
this.processInterval = undefined;
|
|
116
|
+
}
|
|
117
|
+
// Unsubscribe from notifications to stop receiving new job notifications
|
|
118
|
+
if (this.notificationUnsubscribe) {
|
|
119
|
+
log.extend('drain')('unsubscribing from notification channel');
|
|
120
|
+
this.notificationUnsubscribe();
|
|
121
|
+
this.notificationUnsubscribe = undefined;
|
|
122
|
+
}
|
|
123
|
+
const initialRunning = this.runningJobs.length;
|
|
124
|
+
// If no jobs are running, resolve immediately
|
|
125
|
+
if (initialRunning === 0) {
|
|
126
|
+
log.extend('drain')('no running jobs, resolving immediately');
|
|
127
|
+
this.isRunning = false;
|
|
128
|
+
return { completed: 0, running: 0, timedOut: false, aborted: false };
|
|
129
|
+
}
|
|
130
|
+
// Check if already aborted
|
|
131
|
+
if (opts.signal?.aborted) {
|
|
132
|
+
log.extend('drain')('signal already aborted, resolving immediately');
|
|
133
|
+
this.isRunning = false;
|
|
134
|
+
return { completed: 0, running: initialRunning, timedOut: false, aborted: true };
|
|
135
|
+
}
|
|
136
|
+
log.extend('drain')('waiting for %d running jobs to finish', initialRunning);
|
|
137
|
+
// Wait for all running jobs to complete (or timeout/abort)
|
|
138
|
+
return new Promise(resolve => {
|
|
139
|
+
let completed = 0;
|
|
140
|
+
let timeoutId;
|
|
141
|
+
const cleanup = () => {
|
|
142
|
+
this.agenda.off('complete', completeListener);
|
|
143
|
+
if (timeoutId) {
|
|
144
|
+
clearTimeout(timeoutId);
|
|
145
|
+
}
|
|
146
|
+
if (opts.signal) {
|
|
147
|
+
opts.signal.removeEventListener('abort', abortListener);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
const finish = (result) => {
|
|
151
|
+
cleanup();
|
|
152
|
+
this.isRunning = false;
|
|
153
|
+
resolve(result);
|
|
154
|
+
};
|
|
155
|
+
const checkComplete = () => {
|
|
156
|
+
if (this.runningJobs.length === 0) {
|
|
157
|
+
log.extend('drain')('all jobs completed, resolving');
|
|
158
|
+
finish({ completed, running: 0, timedOut: false, aborted: false });
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
// Listen for 'complete' events from the agenda
|
|
162
|
+
const completeListener = () => {
|
|
163
|
+
completed++;
|
|
164
|
+
// Running jobs are removed after the event is emitted,
|
|
165
|
+
// so we check on next tick
|
|
166
|
+
setImmediate(checkComplete);
|
|
167
|
+
};
|
|
168
|
+
// Handle timeout
|
|
169
|
+
if (opts.timeout !== undefined) {
|
|
170
|
+
timeoutId = setTimeout(() => {
|
|
171
|
+
const running = this.runningJobs.length;
|
|
172
|
+
log.extend('drain')('timeout reached, %d jobs still running', running);
|
|
173
|
+
finish({ completed, running, timedOut: true, aborted: false });
|
|
174
|
+
}, opts.timeout);
|
|
175
|
+
}
|
|
176
|
+
// Handle abort signal
|
|
177
|
+
const abortListener = () => {
|
|
178
|
+
const running = this.runningJobs.length;
|
|
179
|
+
log.extend('drain')('abort signal received, %d jobs still running', running);
|
|
180
|
+
finish({ completed, running, timedOut: false, aborted: true });
|
|
181
|
+
};
|
|
182
|
+
if (opts.signal) {
|
|
183
|
+
opts.signal.addEventListener('abort', abortListener);
|
|
184
|
+
}
|
|
185
|
+
this.agenda.on('complete', completeListener);
|
|
186
|
+
// Also check immediately in case jobs finished between our check and listener setup
|
|
187
|
+
checkComplete();
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Handle incoming job notification - triggers immediate processing
|
|
192
|
+
*/
|
|
193
|
+
async handleNotification(notification) {
|
|
194
|
+
if (!this.isRunning) {
|
|
195
|
+
log.extend('handleNotification')('JobProcessor not running, ignoring notification');
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
// Only process notifications for jobs we have definitions for
|
|
199
|
+
if (!this.agenda.definitions[notification.jobName]) {
|
|
200
|
+
log.extend('handleNotification')('no definition for job [%s], ignoring notification', notification.jobName);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
// Check if the job should run soon (within the next scan interval)
|
|
204
|
+
if (notification.nextRunAt && notification.nextRunAt > this.nextScanAt) {
|
|
205
|
+
log.extend('handleNotification')('job [%s:%s] nextRunAt is after nextScanAt, will be picked up by regular scan', notification.jobName, notification.jobId);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
log.extend('handleNotification')('received notification for job [%s:%s], triggering immediate queue fill', notification.jobName, notification.jobId);
|
|
209
|
+
// Fill the queue for this job type and process
|
|
210
|
+
await this.jobQueueFilling(notification.jobName);
|
|
211
|
+
this.jobProcessing();
|
|
212
|
+
}
|
|
213
|
+
// processJobs
|
|
214
|
+
async process() {
|
|
215
|
+
// Make sure an interval has actually been set
|
|
216
|
+
// Prevents race condition with 'Agenda.stop' and already scheduled run
|
|
217
|
+
if (!this.isRunning) {
|
|
218
|
+
log.extend('process')('JobProcessor got stopped already, returning');
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
log.extend('process')('starting to process jobs');
|
|
222
|
+
// Go through each jobName set in 'Agenda.process' and fill the queue with the next jobs
|
|
223
|
+
await Promise.all(Object.keys(this.agenda.definitions).map(async (jobName) => {
|
|
224
|
+
log.extend('process')('queuing up job to process: [%s]', jobName);
|
|
225
|
+
await this.jobQueueFilling(jobName);
|
|
226
|
+
}));
|
|
227
|
+
this.jobProcessing();
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Returns true if a job of the specified name can be locked.
|
|
231
|
+
* Considers maximum locked jobs at any time if self._lockLimit is > 0
|
|
232
|
+
* Considers maximum locked jobs of the specified name at any time if jobDefinition.lockLimit is > 0
|
|
233
|
+
* @param {String} name name of job to check if we should lock or not
|
|
234
|
+
* @returns {boolean} whether or not you should lock job
|
|
235
|
+
*/
|
|
236
|
+
shouldLock(name) {
|
|
237
|
+
const jobDefinition = this.agenda.definitions[name];
|
|
238
|
+
let shouldLock = true;
|
|
239
|
+
// global lock limit
|
|
240
|
+
if (this.totalLockLimit && this.lockedJobs.length >= this.totalLockLimit) {
|
|
241
|
+
shouldLock = false;
|
|
242
|
+
}
|
|
243
|
+
// job specific lock limit
|
|
244
|
+
const status = this.jobStatus[name];
|
|
245
|
+
if (jobDefinition.lockLimit && status && status.locked >= jobDefinition.lockLimit) {
|
|
246
|
+
shouldLock = false;
|
|
247
|
+
}
|
|
248
|
+
log.extend('shouldLock')('job [%s] lock status: shouldLock = %s', name, shouldLock, `${status?.locked} >= ${jobDefinition?.lockLimit}`, `${this.lockedJobs.length} >= ${this.totalLockLimit}`);
|
|
249
|
+
return shouldLock;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Internal method that adds a job to be processed to the local queue
|
|
253
|
+
* @param job - Job to enqueue
|
|
254
|
+
*/
|
|
255
|
+
enqueueJob(job) {
|
|
256
|
+
this.jobQueue.insert(job);
|
|
257
|
+
}
|
|
258
|
+
async findAndLockNextJob(jobName, definition) {
|
|
259
|
+
const lockDeadline = new Date(Date.now().valueOf() - definition.lockLifetime);
|
|
260
|
+
log.extend('findAndLockNextJob')(`looking for lockable jobs for ${jobName} (lock dead line = ${lockDeadline})`);
|
|
261
|
+
// Find ONE and ONLY ONE job and set the 'lockedAt' time so that job begins to be processed
|
|
262
|
+
const result = await this.agenda.db.getNextJobToRun(jobName, this.nextScanAt, lockDeadline, undefined, { lastModifiedBy: this.agenda.attrs.name || undefined });
|
|
263
|
+
if (result) {
|
|
264
|
+
log.extend('findAndLockNextJob')('found a job available to lock, creating a new job on Agenda with id [%s]', result._id);
|
|
265
|
+
return new Job(this.agenda, result, true);
|
|
266
|
+
}
|
|
267
|
+
return undefined;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Internal method used to fill a queue with jobs that can be run
|
|
271
|
+
* @param {String} name fill a queue with specific job name
|
|
272
|
+
* @returns {undefined}
|
|
273
|
+
*/
|
|
274
|
+
async jobQueueFilling(name) {
|
|
275
|
+
this.isJobQueueFilling.set(name, true);
|
|
276
|
+
try {
|
|
277
|
+
// Don't lock because of a limit we have set (lockLimit, etc)
|
|
278
|
+
if (!this.shouldLock(name)) {
|
|
279
|
+
log.extend('jobQueueFilling')('lock limit reached in queue filling for [%s]', name);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
// Set the date of the next time we are going to run _processEvery function
|
|
283
|
+
const now = new Date();
|
|
284
|
+
this.nextScanAt = new Date(now.valueOf() + this.processEvery);
|
|
285
|
+
// For this job name, find the next job to run and lock it!
|
|
286
|
+
const job = await this.findAndLockNextJob(name, this.agenda.definitions[name]);
|
|
287
|
+
// Still have the job?
|
|
288
|
+
// 1. Add it to lock list
|
|
289
|
+
// 2. Add count of locked jobs
|
|
290
|
+
// 3. Queue the job to actually be run now that it is locked
|
|
291
|
+
// 4. Recursively run this same method we are in to check for more available jobs of same type!
|
|
292
|
+
if (job) {
|
|
293
|
+
if (job.attrs.name !== name) {
|
|
294
|
+
throw new Error(`got different job name: ${job.attrs.name} (actual) !== ${name} (expected)`);
|
|
295
|
+
}
|
|
296
|
+
// Before en-queing job make sure we haven't exceed our lock limits
|
|
297
|
+
if (!this.shouldLock(name)) {
|
|
298
|
+
log.extend('jobQueueFilling')('lock limit reached before job was returned. Releasing lock on [%s]', name);
|
|
299
|
+
this.agenda.db.unlockJob(job.attrs);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
log.extend('jobQueueFilling')('[%s:%s] job locked while filling queue', name, job.attrs._id);
|
|
303
|
+
this.agenda.logJobEvent({
|
|
304
|
+
level: 'debug',
|
|
305
|
+
event: 'locked',
|
|
306
|
+
jobId: job.attrs._id?.toString(),
|
|
307
|
+
jobName: name,
|
|
308
|
+
message: 'job locked'
|
|
309
|
+
});
|
|
310
|
+
this.updateStatus(name, 'locked', +1);
|
|
311
|
+
this.lockedJobs.push(job);
|
|
312
|
+
this.enqueueJob(job);
|
|
313
|
+
await this.jobQueueFilling(name);
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
log.extend('jobQueueFilling')('Cannot lock job [%s]', name);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
log.extend('jobQueueFilling')('[%s] job lock failed while filling queue', name, error);
|
|
321
|
+
this.agenda.emit('error', error);
|
|
322
|
+
}
|
|
323
|
+
finally {
|
|
324
|
+
this.isJobQueueFilling.delete(name);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Internal method that processes any jobs in the local queue (array)
|
|
329
|
+
* handledJobs keeps list of already processed jobs
|
|
330
|
+
* @returns {undefined}
|
|
331
|
+
*/
|
|
332
|
+
async jobProcessing(handledJobs = []) {
|
|
333
|
+
// Ensure we have jobs
|
|
334
|
+
if (this.jobQueue.length === 0) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
this.localQueueProcessing += 1;
|
|
338
|
+
try {
|
|
339
|
+
const now = new Date();
|
|
340
|
+
// Check if there is any job that is not blocked by concurrency
|
|
341
|
+
const job = this.jobQueue.returnNextConcurrencyFreeJob(this.jobStatus, handledJobs);
|
|
342
|
+
if (!job) {
|
|
343
|
+
log.extend('jobProcessing')('[%s:%s] there is no job to process');
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
this.jobQueue.remove(job);
|
|
347
|
+
if (!(await job.isExpired())) {
|
|
348
|
+
// check if job has expired (and therefore probably got picked up again by another queue in the meantime)
|
|
349
|
+
// before it even has started to run
|
|
350
|
+
log.extend('jobProcessing')('[%s:%s] there is a job to process (priority = %d)', job.attrs.name, job.attrs._id, job.attrs.priority, job.gotTimerToExecute);
|
|
351
|
+
// If the 'nextRunAt' time is older than the current time, run the job
|
|
352
|
+
// Otherwise, setTimeout that gets called at the time of 'nextRunAt'
|
|
353
|
+
if (!job.attrs.nextRunAt || job.attrs.nextRunAt <= now) {
|
|
354
|
+
log.extend('jobProcessing')('[%s:%s] nextRunAt is in the past, run the job immediately', job.attrs.name, job.attrs._id);
|
|
355
|
+
this.runOrRetry(job);
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
const runIn = job.attrs.nextRunAt.getTime() - now.getTime();
|
|
359
|
+
if (runIn > this.processEvery) {
|
|
360
|
+
// this job is not in the near future, remove it (it will be picked up later)
|
|
361
|
+
log.extend('runOrRetry')('[%s:%s] job is too far away, freeing it up', job.attrs.name, job.attrs._id);
|
|
362
|
+
let lockedJobIndex = this.lockedJobs.indexOf(job);
|
|
363
|
+
if (lockedJobIndex === -1) {
|
|
364
|
+
// lookup by id
|
|
365
|
+
lockedJobIndex = this.lockedJobs.findIndex(j => j.attrs._id?.toString() === job.attrs._id?.toString());
|
|
366
|
+
}
|
|
367
|
+
if (lockedJobIndex === -1) {
|
|
368
|
+
throw new Error(`cannot find job ${job.attrs._id} in locked jobs queue?`);
|
|
369
|
+
}
|
|
370
|
+
this.lockedJobs.splice(lockedJobIndex, 1);
|
|
371
|
+
this.updateStatus(job.attrs.name, 'locked', -1);
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
log.extend('jobProcessing')('[%s:%s] nextRunAt is in the future, calling setTimeout(%d)', job.attrs.name, job.attrs._id, runIn);
|
|
375
|
+
// re add to queue (puts it at the right position in the queue)
|
|
376
|
+
this.jobQueue.insert(job);
|
|
377
|
+
// ensure every job gets a timer to run at the near future time (but also ensure this time is set only once)
|
|
378
|
+
if (!job.gotTimerToExecute) {
|
|
379
|
+
job.gotTimerToExecute = true;
|
|
380
|
+
setTimeout(() => {
|
|
381
|
+
this.jobProcessing();
|
|
382
|
+
}, runIn > MAX_SAFE_32BIT_INTEGER ? MAX_SAFE_32BIT_INTEGER : runIn); // check if runIn is higher than unsined 32 bit int, if so, use this time to recheck,
|
|
383
|
+
// because setTimeout will run in an overflow otherwise and reprocesses immediately
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
handledJobs.push(job.attrs._id);
|
|
389
|
+
if (job && this.localQueueProcessing < this.maxConcurrency) {
|
|
390
|
+
// additionally run again and check if there are more jobs that we can process right now (as long concurrency not reached)
|
|
391
|
+
setImmediate(() => this.jobProcessing(handledJobs));
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
finally {
|
|
395
|
+
this.localQueueProcessing -= 1;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Internal method that tries to run a job and if it fails, retries again!
|
|
400
|
+
* @returns {boolean} processed a job or not
|
|
401
|
+
*/
|
|
402
|
+
async runOrRetry(job) {
|
|
403
|
+
if (!this.isRunning) {
|
|
404
|
+
// const a = new Error();
|
|
405
|
+
// console.log('STACK', a.stack);
|
|
406
|
+
log.extend('runOrRetry')('JobProcessor got stopped already while calling runOrRetry, returning!');
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
const jobDefinition = this.agenda.definitions[job.attrs.name];
|
|
410
|
+
const status = this.jobStatus[job.attrs.name];
|
|
411
|
+
if ((!jobDefinition.concurrency || !status || status.running < jobDefinition.concurrency) &&
|
|
412
|
+
this.runningJobs.length < this.maxConcurrency) {
|
|
413
|
+
// Add to local "running" queue
|
|
414
|
+
this.runningJobs.push(job);
|
|
415
|
+
this.updateStatus(job.attrs.name, 'running', 1);
|
|
416
|
+
let jobIsRunning = true;
|
|
417
|
+
try {
|
|
418
|
+
log.extend('runOrRetry')('[%s:%s] processing job', job.attrs.name, job.attrs._id);
|
|
419
|
+
// check if the job is still alive
|
|
420
|
+
const checkIfJobIsStillAlive = async () => {
|
|
421
|
+
// check every "this.agenda.definitions[job.attrs.name].lockLifetime / 2"" (or at mininum every processEvery)
|
|
422
|
+
const timeout = Math.max(this.processEvery / 2, this.agenda.definitions[job.attrs.name].lockLifetime / 2);
|
|
423
|
+
do {
|
|
424
|
+
await delay(timeout);
|
|
425
|
+
// when job is not running anymore, just finish
|
|
426
|
+
if (!jobIsRunning) {
|
|
427
|
+
log.extend('runOrRetry')('[%s:%s] checkIfJobIsStillAlive detected job is not running anymore. stopping check.', job.attrs.name, job.attrs._id);
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
if (await job.isExpired()) {
|
|
431
|
+
log.extend('runOrRetry')('[%s:%s] checkIfJobIsStillAlive detected an expired job, killing it.', job.attrs.name, job.attrs._id);
|
|
432
|
+
this.agenda.logJobEvent({
|
|
433
|
+
level: 'warn',
|
|
434
|
+
event: 'expired',
|
|
435
|
+
jobId: job.attrs._id?.toString(),
|
|
436
|
+
jobName: job.attrs.name,
|
|
437
|
+
message: `job expired (lock lifetime exceeded)`
|
|
438
|
+
});
|
|
439
|
+
throw new Error(`execution of '${job.attrs.name}' canceled, execution took more than ${this.agenda.definitions[job.attrs.name].lockLifetime}ms. Call touch() for long running jobs to keep them alive.`);
|
|
440
|
+
}
|
|
441
|
+
if (!job.attrs.lockedAt) {
|
|
442
|
+
log.extend('runOrRetry')('[%s:%s] checkIfJobIsStillAlive detected a job without a lockedAt value, killing it.', job.attrs.name, job.attrs._id);
|
|
443
|
+
throw new Error(`execution of '${job.attrs.name}' canceled, no lockedAt date found. Ensure to call touch() for long running jobs to keep them alive.`);
|
|
444
|
+
}
|
|
445
|
+
} while (jobIsRunning);
|
|
446
|
+
};
|
|
447
|
+
// CALL THE ACTUAL METHOD TO PROCESS THE JOB!!!
|
|
448
|
+
await Promise.race([job.run(), checkIfJobIsStillAlive()]);
|
|
449
|
+
log.extend('runOrRetry')('[%s:%s] processing job successfull', job.attrs.name, job.attrs._id);
|
|
450
|
+
// Job isn't in running jobs so throw an error
|
|
451
|
+
if (!this.runningJobs.includes(job)) {
|
|
452
|
+
log.extend('runOrRetry')('[%s] callback was called, job must have been marked as complete already', job.attrs._id);
|
|
453
|
+
throw new Error(`callback already called - job ${job.attrs.name} already marked complete`);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
catch (error) {
|
|
457
|
+
job.cancel(error instanceof Error ? error : undefined);
|
|
458
|
+
log.extend('runOrRetry')('[%s:%s] processing job failed', job.attrs.name, job.attrs._id, error);
|
|
459
|
+
this.agenda.logJobEvent({
|
|
460
|
+
level: 'error',
|
|
461
|
+
event: 'fail',
|
|
462
|
+
jobId: job.attrs._id?.toString(),
|
|
463
|
+
jobName: job.attrs.name,
|
|
464
|
+
message: `job processing error: ${error instanceof Error ? error.message : String(error)}`,
|
|
465
|
+
error: error instanceof Error ? error.message : String(error)
|
|
466
|
+
});
|
|
467
|
+
this.agenda.emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
468
|
+
}
|
|
469
|
+
finally {
|
|
470
|
+
jobIsRunning = false;
|
|
471
|
+
// Remove the job from the running queue
|
|
472
|
+
let runningJobIndex = this.runningJobs.indexOf(job);
|
|
473
|
+
if (runningJobIndex === -1) {
|
|
474
|
+
// lookup by id
|
|
475
|
+
runningJobIndex = this.runningJobs.findIndex(j => j.attrs._id?.toString() === job.attrs._id?.toString());
|
|
476
|
+
}
|
|
477
|
+
if (runningJobIndex === -1) {
|
|
478
|
+
throw new Error(`cannot find job ${job.attrs._id} in running jobs queue?`);
|
|
479
|
+
}
|
|
480
|
+
this.runningJobs.splice(runningJobIndex, 1);
|
|
481
|
+
this.updateStatus(job.attrs.name, 'running', -1);
|
|
482
|
+
// Remove the job from the locked queue
|
|
483
|
+
let lockedJobIndex = this.lockedJobs.indexOf(job);
|
|
484
|
+
if (lockedJobIndex === -1) {
|
|
485
|
+
// lookup by id
|
|
486
|
+
lockedJobIndex = this.lockedJobs.findIndex(j => j.attrs._id?.toString() === job.attrs._id?.toString());
|
|
487
|
+
}
|
|
488
|
+
if (lockedJobIndex === -1) {
|
|
489
|
+
throw new Error(`cannot find job ${job.attrs._id} in locked jobs queue?`);
|
|
490
|
+
}
|
|
491
|
+
this.lockedJobs.splice(lockedJobIndex, 1);
|
|
492
|
+
this.updateStatus(job.attrs.name, 'locked', -1);
|
|
493
|
+
}
|
|
494
|
+
// Re-process jobs now that one has finished
|
|
495
|
+
setImmediate(() => this.jobProcessing());
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
// Run the job later
|
|
499
|
+
log.extend('runOrRetry')('[%s:%s] concurrency preventing immediate run, pushing job to top of queue', job.attrs.name, job.attrs._id);
|
|
500
|
+
this.enqueueJob(job);
|
|
501
|
+
}
|
|
502
|
+
updateStatus(name, key, number) {
|
|
503
|
+
if (!this.jobStatus[name]) {
|
|
504
|
+
this.jobStatus[name] = {
|
|
505
|
+
locked: 0,
|
|
506
|
+
running: 0
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
this.jobStatus[name][key] += number;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
//# sourceMappingURL=JobProcessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JobProcessor.js","sourceRoot":"","sources":["../src/JobProcessor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend implementations have been moved to separate packages:
|
|
3
|
+
*
|
|
4
|
+
* - MongoDB: @quave/agenda-mongodb
|
|
5
|
+
* - PostgreSQL: @agendajs/postgres-backend
|
|
6
|
+
* - Redis: @agendajs/redis-backend
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { Agenda } from 'agenda';
|
|
11
|
+
* import { MongoBackend } from '@quave/agenda-mongodb';
|
|
12
|
+
*
|
|
13
|
+
* const agenda = new Agenda({
|
|
14
|
+
* backend: new MongoBackend({ address: 'mongodb://localhost/agenda' })
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend implementations have been moved to separate packages:
|
|
3
|
+
*
|
|
4
|
+
* - MongoDB: @quave/agenda-mongodb
|
|
5
|
+
* - PostgreSQL: @agendajs/postgres-backend
|
|
6
|
+
* - Redis: @agendajs/redis-backend
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { Agenda } from 'agenda';
|
|
11
|
+
* import { MongoBackend } from '@quave/agenda-mongodb';
|
|
12
|
+
*
|
|
13
|
+
* const agenda = new Agenda({
|
|
14
|
+
* backend: new MongoBackend({ address: 'mongodb://localhost/agenda' })
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
19
|
+
// No exports - backends are in separate packages
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;;AAEH,iDAAiD"}
|