@warlock.js/scheduler 4.0.47 → 4.0.57
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/cjs/cron-parser.d.ts +98 -0
- package/cjs/cron-parser.d.ts.map +1 -0
- package/cjs/cron-parser.js +193 -0
- package/cjs/cron-parser.js.map +1 -0
- package/cjs/index.d.ts +44 -0
- package/cjs/index.d.ts.map +1 -0
- package/cjs/index.js +1 -34
- package/cjs/index.js.map +1 -1
- package/cjs/job.d.ts +332 -0
- package/cjs/job.d.ts.map +1 -0
- package/cjs/job.js +611 -0
- package/cjs/job.js.map +1 -0
- package/cjs/scheduler.d.ts +182 -0
- package/cjs/scheduler.d.ts.map +1 -0
- package/cjs/scheduler.js +313 -0
- package/cjs/scheduler.js.map +1 -0
- package/cjs/types.d.ts +63 -0
- package/cjs/types.d.ts.map +1 -0
- package/cjs/utils.d.ts +3 -0
- package/cjs/utils.d.ts.map +1 -0
- package/esm/cron-parser.d.ts +98 -0
- package/esm/cron-parser.d.ts.map +1 -0
- package/esm/cron-parser.js +193 -0
- package/esm/cron-parser.js.map +1 -0
- package/esm/index.d.ts +44 -0
- package/esm/index.d.ts.map +1 -0
- package/esm/index.js +1 -5
- package/esm/index.js.map +1 -1
- package/esm/job.d.ts +332 -0
- package/esm/job.d.ts.map +1 -0
- package/esm/job.js +611 -0
- package/esm/job.js.map +1 -0
- package/esm/scheduler.d.ts +182 -0
- package/esm/scheduler.d.ts.map +1 -0
- package/esm/scheduler.js +313 -0
- package/esm/scheduler.js.map +1 -0
- package/esm/types.d.ts +63 -0
- package/esm/types.d.ts.map +1 -0
- package/esm/utils.d.ts +3 -0
- package/esm/utils.d.ts.map +1 -0
- package/package.json +27 -40
package/esm/job.js
ADDED
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
import dayjs from'dayjs';import timezone from'dayjs/plugin/timezone.js';import utc from'dayjs/plugin/utc.js';import {CronParser}from'./cron-parser.js';// Enable timezone support
|
|
2
|
+
dayjs.extend(utc);
|
|
3
|
+
dayjs.extend(timezone);
|
|
4
|
+
/**
|
|
5
|
+
* Days of week mapping (lowercase for consistency with Day type)
|
|
6
|
+
*/
|
|
7
|
+
const DAYS_OF_WEEK = [
|
|
8
|
+
"sunday",
|
|
9
|
+
"monday",
|
|
10
|
+
"tuesday",
|
|
11
|
+
"wednesday",
|
|
12
|
+
"thursday",
|
|
13
|
+
"friday",
|
|
14
|
+
"saturday",
|
|
15
|
+
];
|
|
16
|
+
/**
|
|
17
|
+
* Job class represents a scheduled task with configurable timing and execution options.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const job = new Job("cleanup", async () => {
|
|
22
|
+
* await cleanupOldFiles();
|
|
23
|
+
* })
|
|
24
|
+
* .everyDay()
|
|
25
|
+
* .at("03:00")
|
|
26
|
+
* .inTimezone("America/New_York")
|
|
27
|
+
* .preventOverlap()
|
|
28
|
+
* .retry(3, 1000);
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
class Job {
|
|
32
|
+
name;
|
|
33
|
+
_callback;
|
|
34
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
35
|
+
// Private Properties
|
|
36
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
37
|
+
/**
|
|
38
|
+
* Interval configuration for scheduling
|
|
39
|
+
*/
|
|
40
|
+
_intervals = {};
|
|
41
|
+
/**
|
|
42
|
+
* Last execution timestamp
|
|
43
|
+
*/
|
|
44
|
+
_lastRun = null;
|
|
45
|
+
/**
|
|
46
|
+
* Whether the job is currently executing
|
|
47
|
+
*/
|
|
48
|
+
_isRunning = false;
|
|
49
|
+
/**
|
|
50
|
+
* Skip execution if job is already running
|
|
51
|
+
*/
|
|
52
|
+
_skipIfRunning = false;
|
|
53
|
+
/**
|
|
54
|
+
* Retry configuration
|
|
55
|
+
*/
|
|
56
|
+
_retryConfig = null;
|
|
57
|
+
/**
|
|
58
|
+
* Timezone for scheduling (defaults to system timezone)
|
|
59
|
+
*/
|
|
60
|
+
_timezone = null;
|
|
61
|
+
/**
|
|
62
|
+
* Cron expression parser (mutually exclusive with interval config)
|
|
63
|
+
*/
|
|
64
|
+
_cronParser = null;
|
|
65
|
+
/**
|
|
66
|
+
* Promise resolver for completion waiting
|
|
67
|
+
*/
|
|
68
|
+
_completionResolver = null;
|
|
69
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
70
|
+
// Public Properties
|
|
71
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
72
|
+
/**
|
|
73
|
+
* Next scheduled execution time
|
|
74
|
+
*/
|
|
75
|
+
nextRun = null;
|
|
76
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
77
|
+
// Constructor
|
|
78
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
79
|
+
/**
|
|
80
|
+
* Creates a new Job instance
|
|
81
|
+
*
|
|
82
|
+
* @param name - Unique identifier for the job
|
|
83
|
+
* @param callback - Function to execute when the job runs
|
|
84
|
+
*/
|
|
85
|
+
constructor(name, _callback) {
|
|
86
|
+
this.name = name;
|
|
87
|
+
this._callback = _callback;
|
|
88
|
+
}
|
|
89
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
90
|
+
// Public Getters
|
|
91
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
92
|
+
/**
|
|
93
|
+
* Returns true if the job is currently executing
|
|
94
|
+
*/
|
|
95
|
+
get isRunning() {
|
|
96
|
+
return this._isRunning;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Returns the last execution timestamp
|
|
100
|
+
*/
|
|
101
|
+
get lastRun() {
|
|
102
|
+
return this._lastRun;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Returns the current interval configuration (readonly)
|
|
106
|
+
*/
|
|
107
|
+
get intervals() {
|
|
108
|
+
return this._intervals;
|
|
109
|
+
}
|
|
110
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
111
|
+
// Interval Configuration Methods (Fluent API)
|
|
112
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
113
|
+
/**
|
|
114
|
+
* Set a custom interval for job execution
|
|
115
|
+
*
|
|
116
|
+
* @param value - Number of time units
|
|
117
|
+
* @param timeType - Type of time unit
|
|
118
|
+
* @returns this for chaining
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* job.every(5, "minute"); // Run every 5 minutes
|
|
123
|
+
* job.every(2, "hour"); // Run every 2 hours
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
every(value, timeType) {
|
|
127
|
+
this._intervals.every = { type: timeType, value };
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Run job every second (use with caution - high frequency)
|
|
132
|
+
*/
|
|
133
|
+
everySecond() {
|
|
134
|
+
return this.every(1, "second");
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Run job every specified number of seconds
|
|
138
|
+
*/
|
|
139
|
+
everySeconds(seconds) {
|
|
140
|
+
return this.every(seconds, "second");
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Run job every minute
|
|
144
|
+
*/
|
|
145
|
+
everyMinute() {
|
|
146
|
+
return this.every(1, "minute");
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Run job every specified number of minutes
|
|
150
|
+
*/
|
|
151
|
+
everyMinutes(minutes) {
|
|
152
|
+
return this.every(minutes, "minute");
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Run job every hour
|
|
156
|
+
*/
|
|
157
|
+
everyHour() {
|
|
158
|
+
return this.every(1, "hour");
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Run job every specified number of hours
|
|
162
|
+
*/
|
|
163
|
+
everyHours(hours) {
|
|
164
|
+
return this.every(hours, "hour");
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Run job every day at midnight
|
|
168
|
+
*/
|
|
169
|
+
everyDay() {
|
|
170
|
+
return this.every(1, "day");
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Alias for everyDay()
|
|
174
|
+
*/
|
|
175
|
+
daily() {
|
|
176
|
+
return this.everyDay();
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Run job twice a day (every 12 hours)
|
|
180
|
+
*/
|
|
181
|
+
twiceDaily() {
|
|
182
|
+
return this.every(12, "hour");
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Run job every week
|
|
186
|
+
*/
|
|
187
|
+
everyWeek() {
|
|
188
|
+
return this.every(1, "week");
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Alias for everyWeek()
|
|
192
|
+
*/
|
|
193
|
+
weekly() {
|
|
194
|
+
return this.everyWeek();
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Run job every month
|
|
198
|
+
*/
|
|
199
|
+
everyMonth() {
|
|
200
|
+
return this.every(1, "month");
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Alias for everyMonth()
|
|
204
|
+
*/
|
|
205
|
+
monthly() {
|
|
206
|
+
return this.everyMonth();
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Run job every year
|
|
210
|
+
*/
|
|
211
|
+
everyYear() {
|
|
212
|
+
return this.every(1, "year");
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Alias for everyYear()
|
|
216
|
+
*/
|
|
217
|
+
yearly() {
|
|
218
|
+
return this.everyYear();
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Alias for everyMinute() - job runs continuously every minute
|
|
222
|
+
*/
|
|
223
|
+
always() {
|
|
224
|
+
return this.everyMinute();
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Schedule job using a cron expression
|
|
228
|
+
*
|
|
229
|
+
* Supports standard 5-field cron syntax:
|
|
230
|
+
* ```
|
|
231
|
+
* ┌───────────── minute (0-59)
|
|
232
|
+
* │ ┌───────────── hour (0-23)
|
|
233
|
+
* │ │ ┌───────────── day of month (1-31)
|
|
234
|
+
* │ │ │ ┌───────────── month (1-12)
|
|
235
|
+
* │ │ │ │ ┌───────────── day of week (0-6, Sunday = 0)
|
|
236
|
+
* │ │ │ │ │
|
|
237
|
+
* * * * * *
|
|
238
|
+
* ```
|
|
239
|
+
*
|
|
240
|
+
* Supports:
|
|
241
|
+
* - '*' - any value
|
|
242
|
+
* - '5' - specific value
|
|
243
|
+
* - '1,3,5' - list of values
|
|
244
|
+
* - '1-5' - range of values
|
|
245
|
+
* - 'x/5' - step values (every 5)
|
|
246
|
+
* - '1-10/2' - range with step
|
|
247
|
+
*
|
|
248
|
+
* @param expression - Standard 5-field cron expression
|
|
249
|
+
* @returns this for chaining
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* ```typescript
|
|
253
|
+
* job.cron("0 9 * * 1-5"); // 9 AM weekdays
|
|
254
|
+
* job.cron("x/5 * * * *"); // Every 5 minutes
|
|
255
|
+
* job.cron("0 0 1 * *"); // First day of month at midnight
|
|
256
|
+
* job.cron("0 x/2 * * *"); // Every 2 hours
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
cron(expression) {
|
|
260
|
+
this._cronParser = new CronParser(expression);
|
|
261
|
+
// Clear interval config since cron takes precedence
|
|
262
|
+
this._intervals = {};
|
|
263
|
+
return this;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Get the cron expression if one is set
|
|
267
|
+
*/
|
|
268
|
+
get cronExpression() {
|
|
269
|
+
return this._cronParser?.expression ?? null;
|
|
270
|
+
}
|
|
271
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
272
|
+
// Day & Time Configuration Methods
|
|
273
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
274
|
+
/**
|
|
275
|
+
* Schedule job on a specific day
|
|
276
|
+
*
|
|
277
|
+
* @param day - Day of week (string) or day of month (number 1-31)
|
|
278
|
+
* @returns this for chaining
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```typescript
|
|
282
|
+
* job.on("monday"); // Run on Mondays
|
|
283
|
+
* job.on(15); // Run on the 15th of each month
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
on(day) {
|
|
287
|
+
if (typeof day === "number" && (day < 1 || day > 31)) {
|
|
288
|
+
throw new Error("Invalid day of the month. Must be between 1 and 31.");
|
|
289
|
+
}
|
|
290
|
+
this._intervals.day = day;
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Schedule job at a specific time
|
|
295
|
+
*
|
|
296
|
+
* @param time - Time in HH:mm or HH:mm:ss format
|
|
297
|
+
* @returns this for chaining
|
|
298
|
+
*
|
|
299
|
+
* @example
|
|
300
|
+
* ```typescript
|
|
301
|
+
* job.daily().at("09:00"); // Run daily at 9 AM
|
|
302
|
+
* job.weekly().at("14:30"); // Run weekly at 2:30 PM
|
|
303
|
+
* ```
|
|
304
|
+
*/
|
|
305
|
+
at(time) {
|
|
306
|
+
// Validate time format
|
|
307
|
+
if (!/^\d{1,2}:\d{2}(:\d{2})?$/.test(time)) {
|
|
308
|
+
throw new Error("Invalid time format. Use HH:mm or HH:mm:ss.");
|
|
309
|
+
}
|
|
310
|
+
this._intervals.time = time;
|
|
311
|
+
return this;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Run task at the beginning of the specified time period
|
|
315
|
+
*
|
|
316
|
+
* @param type - Time type (day, month, year)
|
|
317
|
+
*/
|
|
318
|
+
beginOf(type) {
|
|
319
|
+
const time = "00:00";
|
|
320
|
+
switch (type) {
|
|
321
|
+
case "day":
|
|
322
|
+
break;
|
|
323
|
+
case "month":
|
|
324
|
+
this.on(1);
|
|
325
|
+
break;
|
|
326
|
+
case "year":
|
|
327
|
+
this.on(1);
|
|
328
|
+
this.every(1, "year");
|
|
329
|
+
break;
|
|
330
|
+
default:
|
|
331
|
+
throw new Error(`Unsupported type for beginOf: ${type}`);
|
|
332
|
+
}
|
|
333
|
+
return this.at(time);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Run task at the end of the specified time period
|
|
337
|
+
*
|
|
338
|
+
* @param type - Time type (day, month, year)
|
|
339
|
+
*/
|
|
340
|
+
endOf(type) {
|
|
341
|
+
const now = this._now();
|
|
342
|
+
const time = "23:59";
|
|
343
|
+
switch (type) {
|
|
344
|
+
case "day":
|
|
345
|
+
break;
|
|
346
|
+
case "month":
|
|
347
|
+
this.on(now.endOf("month").date());
|
|
348
|
+
break;
|
|
349
|
+
case "year":
|
|
350
|
+
this.on(31);
|
|
351
|
+
this.every(1, "year");
|
|
352
|
+
break;
|
|
353
|
+
default:
|
|
354
|
+
throw new Error(`Unsupported type for endOf: ${type}`);
|
|
355
|
+
}
|
|
356
|
+
return this.at(time);
|
|
357
|
+
}
|
|
358
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
359
|
+
// Timezone Configuration
|
|
360
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
361
|
+
/**
|
|
362
|
+
* Set the timezone for this job's scheduling
|
|
363
|
+
*
|
|
364
|
+
* @param tz - IANA timezone string (e.g., "America/New_York", "Europe/London")
|
|
365
|
+
* @returns this for chaining
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
368
|
+
* ```typescript
|
|
369
|
+
* job.daily().at("09:00").inTimezone("America/New_York");
|
|
370
|
+
* ```
|
|
371
|
+
*/
|
|
372
|
+
inTimezone(tz) {
|
|
373
|
+
this._timezone = tz;
|
|
374
|
+
return this;
|
|
375
|
+
}
|
|
376
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
377
|
+
// Execution Options
|
|
378
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
379
|
+
/**
|
|
380
|
+
* Prevent overlapping executions of this job
|
|
381
|
+
*
|
|
382
|
+
* When enabled, if the job is already running when it's scheduled to run again,
|
|
383
|
+
* the new execution will be skipped.
|
|
384
|
+
*
|
|
385
|
+
* @param skip - Whether to skip if already running (default: true)
|
|
386
|
+
* @returns this for chaining
|
|
387
|
+
*/
|
|
388
|
+
preventOverlap(skip = true) {
|
|
389
|
+
this._skipIfRunning = skip;
|
|
390
|
+
return this;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Configure automatic retry on failure
|
|
394
|
+
*
|
|
395
|
+
* @param maxRetries - Maximum number of retry attempts
|
|
396
|
+
* @param delay - Delay between retries in milliseconds
|
|
397
|
+
* @param backoffMultiplier - Optional multiplier for exponential backoff
|
|
398
|
+
* @returns this for chaining
|
|
399
|
+
*
|
|
400
|
+
* @example
|
|
401
|
+
* ```typescript
|
|
402
|
+
* job.retry(3, 1000); // Retry 3 times with 1s delay
|
|
403
|
+
* job.retry(5, 1000, 2); // Exponential backoff: 1s, 2s, 4s, 8s, 16s
|
|
404
|
+
* ```
|
|
405
|
+
*/
|
|
406
|
+
retry(maxRetries, delay = 1000, backoffMultiplier) {
|
|
407
|
+
this._retryConfig = {
|
|
408
|
+
maxRetries,
|
|
409
|
+
delay,
|
|
410
|
+
backoffMultiplier,
|
|
411
|
+
};
|
|
412
|
+
return this;
|
|
413
|
+
}
|
|
414
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
415
|
+
// Execution Control
|
|
416
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
417
|
+
/**
|
|
418
|
+
* Terminate the job and clear all scheduling data
|
|
419
|
+
*/
|
|
420
|
+
terminate() {
|
|
421
|
+
this._intervals = {};
|
|
422
|
+
this.nextRun = null;
|
|
423
|
+
this._lastRun = null;
|
|
424
|
+
this._isRunning = false;
|
|
425
|
+
return this;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Prepare the job by calculating the next run time
|
|
429
|
+
* Called by the scheduler when starting
|
|
430
|
+
*/
|
|
431
|
+
prepare() {
|
|
432
|
+
this._determineNextRun();
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Determine if the job should run now
|
|
436
|
+
*
|
|
437
|
+
* @returns true if the job should execute
|
|
438
|
+
*/
|
|
439
|
+
shouldRun() {
|
|
440
|
+
// Skip if already running and overlap prevention is enabled
|
|
441
|
+
if (this._skipIfRunning && this._isRunning) {
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
return this.nextRun !== null && this._now().isAfter(this.nextRun);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Execute the job
|
|
448
|
+
*
|
|
449
|
+
* @returns Promise resolving to the job result
|
|
450
|
+
*/
|
|
451
|
+
async run() {
|
|
452
|
+
const startTime = Date.now();
|
|
453
|
+
this._isRunning = true;
|
|
454
|
+
try {
|
|
455
|
+
const result = await this._executeWithRetry();
|
|
456
|
+
this._lastRun = this._now();
|
|
457
|
+
this._determineNextRun();
|
|
458
|
+
return {
|
|
459
|
+
success: true,
|
|
460
|
+
duration: Date.now() - startTime,
|
|
461
|
+
retries: result.retries || 0,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
catch (error) {
|
|
465
|
+
return {
|
|
466
|
+
success: false,
|
|
467
|
+
duration: Date.now() - startTime,
|
|
468
|
+
error,
|
|
469
|
+
retries: this._retryConfig?.maxRetries ?? 0,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
finally {
|
|
473
|
+
this._isRunning = false;
|
|
474
|
+
// Resolve any waiting completion promises
|
|
475
|
+
if (this._completionResolver) {
|
|
476
|
+
this._completionResolver();
|
|
477
|
+
this._completionResolver = null;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Wait for the job to complete
|
|
483
|
+
* Useful for graceful shutdown
|
|
484
|
+
*
|
|
485
|
+
* @returns Promise that resolves when the job completes
|
|
486
|
+
*/
|
|
487
|
+
waitForCompletion() {
|
|
488
|
+
if (!this._isRunning) {
|
|
489
|
+
return Promise.resolve();
|
|
490
|
+
}
|
|
491
|
+
return new Promise((resolve) => {
|
|
492
|
+
this._completionResolver = resolve;
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
496
|
+
// Private Methods
|
|
497
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
498
|
+
/**
|
|
499
|
+
* Get current time, respecting timezone if set
|
|
500
|
+
*/
|
|
501
|
+
_now() {
|
|
502
|
+
return this._timezone ? dayjs().tz(this._timezone) : dayjs();
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Execute the callback with retry logic
|
|
506
|
+
*/
|
|
507
|
+
async _executeWithRetry() {
|
|
508
|
+
let lastError;
|
|
509
|
+
let attempts = 0;
|
|
510
|
+
const maxAttempts = (this._retryConfig?.maxRetries ?? 0) + 1;
|
|
511
|
+
while (attempts < maxAttempts) {
|
|
512
|
+
try {
|
|
513
|
+
await this._callback(this);
|
|
514
|
+
return { retries: attempts };
|
|
515
|
+
}
|
|
516
|
+
catch (error) {
|
|
517
|
+
lastError = error;
|
|
518
|
+
attempts++;
|
|
519
|
+
if (attempts < maxAttempts && this._retryConfig) {
|
|
520
|
+
const delay = this._calculateRetryDelay(attempts);
|
|
521
|
+
await this._sleep(delay);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
throw lastError;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Calculate retry delay with optional exponential backoff
|
|
529
|
+
*/
|
|
530
|
+
_calculateRetryDelay(attempt) {
|
|
531
|
+
if (!this._retryConfig)
|
|
532
|
+
return 0;
|
|
533
|
+
const { delay, backoffMultiplier } = this._retryConfig;
|
|
534
|
+
if (backoffMultiplier) {
|
|
535
|
+
return delay * Math.pow(backoffMultiplier, attempt - 1);
|
|
536
|
+
}
|
|
537
|
+
return delay;
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Sleep for specified milliseconds
|
|
541
|
+
*/
|
|
542
|
+
_sleep(ms) {
|
|
543
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Calculate the next run time based on interval or cron configuration
|
|
547
|
+
*/
|
|
548
|
+
_determineNextRun() {
|
|
549
|
+
// If using cron expression, delegate to cron parser
|
|
550
|
+
if (this._cronParser) {
|
|
551
|
+
const now = this._now();
|
|
552
|
+
this.nextRun = this._cronParser.nextRun(now);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
// Otherwise use interval-based scheduling
|
|
556
|
+
let date = this._lastRun ? this._lastRun.add(1, "second") : this._now();
|
|
557
|
+
// Apply interval
|
|
558
|
+
if (this._intervals.every?.value && this._intervals.every?.type) {
|
|
559
|
+
date = date.add(this._intervals.every.value, this._intervals.every.type);
|
|
560
|
+
}
|
|
561
|
+
// Apply day constraint
|
|
562
|
+
if (this._intervals.day !== undefined) {
|
|
563
|
+
if (typeof this._intervals.day === "number") {
|
|
564
|
+
date = date.date(this._intervals.day);
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
const targetDay = DAYS_OF_WEEK.indexOf(this._intervals.day);
|
|
568
|
+
if (targetDay !== -1) {
|
|
569
|
+
date = date.day(targetDay);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
// Apply time constraint
|
|
574
|
+
if (this._intervals.time) {
|
|
575
|
+
const parts = this._intervals.time.split(":").map(Number);
|
|
576
|
+
const [hour, minute, second = 0] = parts;
|
|
577
|
+
date = date.hour(hour).minute(minute).second(second).millisecond(0);
|
|
578
|
+
}
|
|
579
|
+
// Ensure the next run is in the future
|
|
580
|
+
while (date.isBefore(this._now())) {
|
|
581
|
+
if (this._intervals.every?.value && this._intervals.every?.type) {
|
|
582
|
+
date = date.add(this._intervals.every.value, this._intervals.every.type);
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
// Default to adding one day if there's no specific interval defined
|
|
586
|
+
date = date.add(1, "day");
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
this.nextRun = date;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
593
|
+
// Factory Function
|
|
594
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
595
|
+
/**
|
|
596
|
+
* Factory function to create a new Job instance
|
|
597
|
+
*
|
|
598
|
+
* @param name - Unique identifier for the job
|
|
599
|
+
* @param callback - Function to execute when the job runs
|
|
600
|
+
* @returns New Job instance
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* ```typescript
|
|
604
|
+
* const cleanupJob = job("cleanup", async () => {
|
|
605
|
+
* await db.deleteExpiredTokens();
|
|
606
|
+
* }).daily().at("03:00");
|
|
607
|
+
* ```
|
|
608
|
+
*/
|
|
609
|
+
function job(name, callback) {
|
|
610
|
+
return new Job(name, callback);
|
|
611
|
+
}export{Job,job};//# sourceMappingURL=job.js.map
|
package/esm/job.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job.js","sources":["../src/job.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|