@stacksjs/scheduler 0.59.11 → 0.61.1
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/dist/index.js +151 -150
- package/package.json +4 -3
- package/src/job.ts +47 -82
- package/src/schedule.ts +5 -5
- package/src/time.ts +92 -196
- package/src/types/cron.ts +23 -49
- package/src/types/utils.ts +2 -9
- package/src/utils.ts +4 -7
- package/dist/constants.d.ts +0 -74
- package/dist/errors.d.ts +0 -5
- package/dist/index.d.ts +0 -7
- package/dist/job.d.ts +0 -32
- package/dist/schedule.d.ts +0 -29
- package/dist/time.d.ts +0 -159
- package/dist/types/cron.d.ts +0 -49
- package/dist/types/utils.d.ts +0 -3
- package/dist/utils.d.ts +0 -12
package/dist/index.js
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
// src/schedule.ts
|
|
3
3
|
import {log} from "@stacksjs/cli";
|
|
4
4
|
|
|
5
|
+
// src/job.ts
|
|
6
|
+
import {spawn} from "child_process";
|
|
7
|
+
|
|
8
|
+
// src/errors.ts
|
|
9
|
+
class CronError extends Error {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class ExclusiveParametersError extends CronError {
|
|
16
|
+
constructor(param1, param2) {
|
|
17
|
+
super(`You can't specify both ${param1} and ${param2}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
5
21
|
// src/time.ts
|
|
6
22
|
import {DateTime} from "luxon";
|
|
7
23
|
|
|
@@ -81,19 +97,6 @@ var PRESETS = Object.freeze({
|
|
|
81
97
|
var RE_WILDCARDS = /\*/g;
|
|
82
98
|
var RE_RANGE = /^(\d+)(?:-(\d+))?(?:\/(\d+))?$/g;
|
|
83
99
|
|
|
84
|
-
// src/errors.ts
|
|
85
|
-
class CronError extends Error {
|
|
86
|
-
constructor() {
|
|
87
|
-
super(...arguments);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
class ExclusiveParametersError extends CronError {
|
|
92
|
-
constructor(param1, param2) {
|
|
93
|
-
super(`You can't specify both ${param1} and ${param2}`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
100
|
// src/utils.ts
|
|
98
101
|
function getRecordKeys(record) {
|
|
99
102
|
return Object.keys(record);
|
|
@@ -192,14 +195,13 @@ class CronTime {
|
|
|
192
195
|
}
|
|
193
196
|
if (i === undefined || Number.isNaN(i) || i < 0) {
|
|
194
197
|
return this.getNextDateFrom(date);
|
|
195
|
-
} else {
|
|
196
|
-
const dates = [];
|
|
197
|
-
for (;i > 0; i--) {
|
|
198
|
-
date = this.getNextDateFrom(date);
|
|
199
|
-
dates.push(date);
|
|
200
|
-
}
|
|
201
|
-
return dates;
|
|
202
198
|
}
|
|
199
|
+
const dates = [];
|
|
200
|
+
for (;i > 0; i--) {
|
|
201
|
+
date = this.getNextDateFrom(date);
|
|
202
|
+
dates.push(date);
|
|
203
|
+
}
|
|
204
|
+
return dates;
|
|
203
205
|
}
|
|
204
206
|
getTimeout() {
|
|
205
207
|
return Math.max(-1, this.sendAt().toMillis() - DateTime.local().toMillis());
|
|
@@ -323,7 +325,10 @@ class CronTime {
|
|
|
323
325
|
return date;
|
|
324
326
|
}
|
|
325
327
|
_findPreviousDSTJump(date) {
|
|
326
|
-
let expectedMinute
|
|
328
|
+
let expectedMinute;
|
|
329
|
+
let expectedHour;
|
|
330
|
+
let actualMinute;
|
|
331
|
+
let actualHour;
|
|
327
332
|
let maybeJumpingPoint = date;
|
|
328
333
|
const iterationLimit = 1440;
|
|
329
334
|
let iteration = 0;
|
|
@@ -344,10 +349,7 @@ class CronTime {
|
|
|
344
349
|
const afterJumpingPoint = maybeJumpingPoint.plus({ minute: 1 }).set({ second: 0, millisecond: 0 });
|
|
345
350
|
const beforeJumpingPoint = afterJumpingPoint.minus({ second: 1 });
|
|
346
351
|
if (date.month + 1 in this.month && date.day in this.dayOfMonth && this._getWeekDay(date) in this.dayOfWeek) {
|
|
347
|
-
return [
|
|
348
|
-
this._checkTimeInSkippedRange(beforeJumpingPoint, afterJumpingPoint),
|
|
349
|
-
afterJumpingPoint
|
|
350
|
-
];
|
|
352
|
+
return [this._checkTimeInSkippedRange(beforeJumpingPoint, afterJumpingPoint), afterJumpingPoint];
|
|
351
353
|
}
|
|
352
354
|
return [false, afterJumpingPoint];
|
|
353
355
|
}
|
|
@@ -358,11 +360,11 @@ class CronTime {
|
|
|
358
360
|
const isHourJump = startingMinute === 0 && afterJumpingPoint.minute === 0;
|
|
359
361
|
if (hourRangeSize === 2 && isHourJump) {
|
|
360
362
|
return startingHour in this.hour;
|
|
361
|
-
}
|
|
363
|
+
}
|
|
364
|
+
if (hourRangeSize === 1) {
|
|
362
365
|
return startingHour in this.hour && this._checkTimeInSkippedRangeSingleHour(startingMinute, afterJumpingPoint.minute);
|
|
363
|
-
} else {
|
|
364
|
-
return this._checkTimeInSkippedRangeMultiHour(startingHour, startingMinute, afterJumpingPoint.hour, afterJumpingPoint.minute);
|
|
365
366
|
}
|
|
367
|
+
return this._checkTimeInSkippedRangeMultiHour(startingHour, startingMinute, afterJumpingPoint.hour, afterJumpingPoint.minute);
|
|
366
368
|
}
|
|
367
369
|
_checkTimeInSkippedRangeSingleHour(startMinute, endMinute) {
|
|
368
370
|
for (let minute = startMinute;minute < endMinute; ++minute) {
|
|
@@ -381,10 +383,9 @@ class CronTime {
|
|
|
381
383
|
const selectRange = (forHour) => {
|
|
382
384
|
if (forHour === startHour)
|
|
383
385
|
return firstHourMinuteRange;
|
|
384
|
-
|
|
386
|
+
if (forHour === endHour)
|
|
385
387
|
return lastHourMinuteRange;
|
|
386
|
-
|
|
387
|
-
return middleHourMinuteRange;
|
|
388
|
+
return middleHourMinuteRange;
|
|
388
389
|
};
|
|
389
390
|
for (let hour = startHour;hour <= endHour; ++hour) {
|
|
390
391
|
if (!(hour in this.hour))
|
|
@@ -487,7 +488,7 @@ class CronTime {
|
|
|
487
488
|
if (unit === "dayOfWeek") {
|
|
488
489
|
if (!typeObj[0] && !!typeObj[7])
|
|
489
490
|
typeObj[0] = typeObj[7];
|
|
490
|
-
|
|
491
|
+
typeObj[7] = undefined;
|
|
491
492
|
}
|
|
492
493
|
} else {
|
|
493
494
|
throw new CronError(`Field (${unit}) cannot be parsed`);
|
|
@@ -496,100 +497,8 @@ class CronTime {
|
|
|
496
497
|
}
|
|
497
498
|
}
|
|
498
499
|
|
|
499
|
-
// src/schedule.ts
|
|
500
|
-
function sendAt(cronTime) {
|
|
501
|
-
return new CronTime(cronTime).sendAt();
|
|
502
|
-
}
|
|
503
|
-
function timeout(cronTime) {
|
|
504
|
-
return new CronTime(cronTime).getTimeout();
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
class Schedule {
|
|
508
|
-
cronPattern = "";
|
|
509
|
-
timezone = "America/Los_Angeles";
|
|
510
|
-
task;
|
|
511
|
-
constructor(task) {
|
|
512
|
-
this.task = task;
|
|
513
|
-
}
|
|
514
|
-
everySecond() {
|
|
515
|
-
this.cronPattern = "* * * * * *";
|
|
516
|
-
return this;
|
|
517
|
-
}
|
|
518
|
-
everyMinute() {
|
|
519
|
-
this.cronPattern = "0 * * * * *";
|
|
520
|
-
return this;
|
|
521
|
-
}
|
|
522
|
-
everyTwoMinutes() {
|
|
523
|
-
this.cronPattern = "*/2 * * * * *";
|
|
524
|
-
return this;
|
|
525
|
-
}
|
|
526
|
-
everyFiveMinutes() {
|
|
527
|
-
this.cronPattern = "*/5 * * * *";
|
|
528
|
-
return this;
|
|
529
|
-
}
|
|
530
|
-
everyTenMinutes() {
|
|
531
|
-
this.cronPattern = "*/10 * * * *";
|
|
532
|
-
return this;
|
|
533
|
-
}
|
|
534
|
-
everyThirtyMinutes() {
|
|
535
|
-
this.cronPattern = "*/30 * * * *";
|
|
536
|
-
return this;
|
|
537
|
-
}
|
|
538
|
-
hourly() {
|
|
539
|
-
this.cronPattern = "0 0 * * * *";
|
|
540
|
-
return this;
|
|
541
|
-
}
|
|
542
|
-
daily() {
|
|
543
|
-
this.cronPattern = "0 0 0 * * *";
|
|
544
|
-
return this;
|
|
545
|
-
}
|
|
546
|
-
weekly() {
|
|
547
|
-
this.cronPattern = "0 0 0 * * 0";
|
|
548
|
-
return this;
|
|
549
|
-
}
|
|
550
|
-
monthly() {
|
|
551
|
-
this.cronPattern = "0 0 0 1 * *";
|
|
552
|
-
return this;
|
|
553
|
-
}
|
|
554
|
-
yearly() {
|
|
555
|
-
this.cronPattern = "0 0 0 1 1 *";
|
|
556
|
-
return this;
|
|
557
|
-
}
|
|
558
|
-
onDays(days) {
|
|
559
|
-
const dayPattern = days.join(",");
|
|
560
|
-
this.cronPattern = `0 0 0 * * ${dayPattern}`;
|
|
561
|
-
return this;
|
|
562
|
-
}
|
|
563
|
-
at(time2) {
|
|
564
|
-
const [hour, minute] = time2.split(":").map(Number);
|
|
565
|
-
this.cronPattern = `${minute} ${hour} * * *`;
|
|
566
|
-
return this;
|
|
567
|
-
}
|
|
568
|
-
setTimeZone(timezone) {
|
|
569
|
-
this.timezone = timezone;
|
|
570
|
-
return this;
|
|
571
|
-
}
|
|
572
|
-
start() {
|
|
573
|
-
new CronJob(this.cronPattern, this.task, null, true, this.timezone);
|
|
574
|
-
log.info(`Scheduled task with pattern: ${this.cronPattern} in timezone: ${this.timezone}`);
|
|
575
|
-
}
|
|
576
|
-
job(path) {
|
|
577
|
-
log.info(`Scheduling job: ${path}`);
|
|
578
|
-
return this;
|
|
579
|
-
}
|
|
580
|
-
action(path) {
|
|
581
|
-
log.info(`Scheduling action: ${path}`);
|
|
582
|
-
return this;
|
|
583
|
-
}
|
|
584
|
-
static command(cmd) {
|
|
585
|
-
this.cmd = cmd;
|
|
586
|
-
return this;
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
500
|
// src/job.ts
|
|
591
|
-
|
|
592
|
-
class CronJob2 {
|
|
501
|
+
class CronJob {
|
|
593
502
|
cronTime;
|
|
594
503
|
running = false;
|
|
595
504
|
unrefTimeout = false;
|
|
@@ -624,12 +533,12 @@ class CronJob2 {
|
|
|
624
533
|
if (params.timeZone != null && params.utcOffset != null)
|
|
625
534
|
throw new ExclusiveParametersError("timeZone", "utcOffset");
|
|
626
535
|
if (params.timeZone != null) {
|
|
627
|
-
return new
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
return new CronJob2(params.cronTime, params.onTick, params.onComplete, params.start, params.timeZone, params.context, params.runOnInit, params.utcOffset, params.unrefTimeout);
|
|
536
|
+
return new CronJob(params.cronTime, params.onTick, params.onComplete, params.start, params.timeZone, params.context, params.runOnInit, params.utcOffset, params.unrefTimeout);
|
|
537
|
+
}
|
|
538
|
+
if (params.utcOffset != null) {
|
|
539
|
+
return new CronJob(params.cronTime, params.onTick, params.onComplete, params.start, null, params.context, params.runOnInit, params.utcOffset, params.unrefTimeout);
|
|
632
540
|
}
|
|
541
|
+
return new CronJob(params.cronTime, params.onTick, params.onComplete, params.start, params.timeZone, params.context, params.runOnInit, params.utcOffset, params.unrefTimeout);
|
|
633
542
|
}
|
|
634
543
|
_fnWrap(cmd) {
|
|
635
544
|
switch (typeof cmd) {
|
|
@@ -645,17 +554,17 @@ class CronJob2 {
|
|
|
645
554
|
}
|
|
646
555
|
}
|
|
647
556
|
}
|
|
648
|
-
addCallback(
|
|
649
|
-
if (typeof
|
|
650
|
-
this._callbacks.push(
|
|
557
|
+
addCallback(callback) {
|
|
558
|
+
if (typeof callback === "function")
|
|
559
|
+
this._callbacks.push(callback);
|
|
651
560
|
}
|
|
652
|
-
setTime(
|
|
653
|
-
if (!(
|
|
561
|
+
setTime(time2) {
|
|
562
|
+
if (!(time2 instanceof CronTime))
|
|
654
563
|
throw new CronError("time must be an instance of CronTime.");
|
|
655
564
|
const wasRunning = this.running;
|
|
656
565
|
this.stop();
|
|
657
|
-
this.cronTime =
|
|
658
|
-
if (
|
|
566
|
+
this.cronTime = time2;
|
|
567
|
+
if (time2.realDate)
|
|
659
568
|
this.runOnce = true;
|
|
660
569
|
if (wasRunning)
|
|
661
570
|
this.start();
|
|
@@ -665,7 +574,9 @@ class CronJob2 {
|
|
|
665
574
|
}
|
|
666
575
|
fireOnTick() {
|
|
667
576
|
try {
|
|
668
|
-
|
|
577
|
+
for (const callback of this._callbacks) {
|
|
578
|
+
callback.call(this.context, this.onComplete);
|
|
579
|
+
}
|
|
669
580
|
} catch (error) {
|
|
670
581
|
if (this._errorHandler && error instanceof Error) {
|
|
671
582
|
this._errorHandler(error);
|
|
@@ -681,17 +592,16 @@ class CronJob2 {
|
|
|
681
592
|
if (this.running)
|
|
682
593
|
return;
|
|
683
594
|
const MAXDELAY = 2147483647;
|
|
684
|
-
let
|
|
595
|
+
let timeout = this.cronTime.getTimeout();
|
|
685
596
|
let remaining = 0;
|
|
686
597
|
let startTime;
|
|
687
598
|
const setCronTimeout = (t) => {
|
|
688
|
-
startTime = Date.now();
|
|
689
599
|
this._timeout = setTimeout(callbackWrapper, t);
|
|
690
600
|
if (this.unrefTimeout && typeof this._timeout.unref === "function")
|
|
691
601
|
this._timeout.unref();
|
|
692
602
|
};
|
|
693
603
|
const callbackWrapper = () => {
|
|
694
|
-
const diff = startTime +
|
|
604
|
+
const diff = startTime + timeout - Date.now();
|
|
695
605
|
if (diff > 0) {
|
|
696
606
|
let newTimeout = this.cronTime.getTimeout();
|
|
697
607
|
if (newTimeout > diff)
|
|
@@ -701,12 +611,12 @@ class CronJob2 {
|
|
|
701
611
|
if (remaining) {
|
|
702
612
|
if (remaining > MAXDELAY) {
|
|
703
613
|
remaining -= MAXDELAY;
|
|
704
|
-
|
|
614
|
+
timeout = MAXDELAY;
|
|
705
615
|
} else {
|
|
706
|
-
|
|
616
|
+
timeout = remaining;
|
|
707
617
|
remaining = 0;
|
|
708
618
|
}
|
|
709
|
-
setCronTimeout(
|
|
619
|
+
setCronTimeout(timeout);
|
|
710
620
|
} else {
|
|
711
621
|
this.lastExecution = new Date;
|
|
712
622
|
this.running = false;
|
|
@@ -715,13 +625,13 @@ class CronJob2 {
|
|
|
715
625
|
this.fireOnTick();
|
|
716
626
|
}
|
|
717
627
|
};
|
|
718
|
-
if (
|
|
628
|
+
if (timeout >= 0) {
|
|
719
629
|
this.running = true;
|
|
720
|
-
if (
|
|
721
|
-
remaining =
|
|
722
|
-
|
|
630
|
+
if (timeout > MAXDELAY) {
|
|
631
|
+
remaining = timeout - MAXDELAY;
|
|
632
|
+
timeout = MAXDELAY;
|
|
723
633
|
}
|
|
724
|
-
setCronTimeout(
|
|
634
|
+
setCronTimeout(timeout);
|
|
725
635
|
} else {
|
|
726
636
|
this.stop();
|
|
727
637
|
}
|
|
@@ -738,6 +648,97 @@ class CronJob2 {
|
|
|
738
648
|
}
|
|
739
649
|
}
|
|
740
650
|
|
|
651
|
+
// src/schedule.ts
|
|
652
|
+
function sendAt(cronTime) {
|
|
653
|
+
return new CronTime(cronTime).sendAt();
|
|
654
|
+
}
|
|
655
|
+
function timeout(cronTime) {
|
|
656
|
+
return new CronTime(cronTime).getTimeout();
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
class Schedule {
|
|
660
|
+
cronPattern = "";
|
|
661
|
+
timezone = "America/Los_Angeles";
|
|
662
|
+
task;
|
|
663
|
+
constructor(task) {
|
|
664
|
+
this.task = task;
|
|
665
|
+
}
|
|
666
|
+
everySecond() {
|
|
667
|
+
this.cronPattern = "* * * * * *";
|
|
668
|
+
return this;
|
|
669
|
+
}
|
|
670
|
+
everyMinute() {
|
|
671
|
+
this.cronPattern = "0 * * * * *";
|
|
672
|
+
return this;
|
|
673
|
+
}
|
|
674
|
+
everyTwoMinutes() {
|
|
675
|
+
this.cronPattern = "*/2 * * * * *";
|
|
676
|
+
return this;
|
|
677
|
+
}
|
|
678
|
+
everyFiveMinutes() {
|
|
679
|
+
this.cronPattern = "*/5 * * * *";
|
|
680
|
+
return this;
|
|
681
|
+
}
|
|
682
|
+
everyTenMinutes() {
|
|
683
|
+
this.cronPattern = "*/10 * * * *";
|
|
684
|
+
return this;
|
|
685
|
+
}
|
|
686
|
+
everyThirtyMinutes() {
|
|
687
|
+
this.cronPattern = "*/30 * * * *";
|
|
688
|
+
return this;
|
|
689
|
+
}
|
|
690
|
+
hourly() {
|
|
691
|
+
this.cronPattern = "0 0 * * * *";
|
|
692
|
+
return this;
|
|
693
|
+
}
|
|
694
|
+
daily() {
|
|
695
|
+
this.cronPattern = "0 0 0 * * *";
|
|
696
|
+
return this;
|
|
697
|
+
}
|
|
698
|
+
weekly() {
|
|
699
|
+
this.cronPattern = "0 0 0 * * 0";
|
|
700
|
+
return this;
|
|
701
|
+
}
|
|
702
|
+
monthly() {
|
|
703
|
+
this.cronPattern = "0 0 0 1 * *";
|
|
704
|
+
return this;
|
|
705
|
+
}
|
|
706
|
+
yearly() {
|
|
707
|
+
this.cronPattern = "0 0 0 1 1 *";
|
|
708
|
+
return this;
|
|
709
|
+
}
|
|
710
|
+
onDays(days) {
|
|
711
|
+
const dayPattern = days.join(",");
|
|
712
|
+
this.cronPattern = `0 0 0 * * ${dayPattern}`;
|
|
713
|
+
return this;
|
|
714
|
+
}
|
|
715
|
+
at(time3) {
|
|
716
|
+
const [hour, minute] = time3.split(":").map(Number);
|
|
717
|
+
this.cronPattern = `${minute} ${hour} * * *`;
|
|
718
|
+
return this;
|
|
719
|
+
}
|
|
720
|
+
setTimeZone(timezone) {
|
|
721
|
+
this.timezone = timezone;
|
|
722
|
+
return this;
|
|
723
|
+
}
|
|
724
|
+
start() {
|
|
725
|
+
new CronJob(this.cronPattern, this.task, null, true, this.timezone);
|
|
726
|
+
log.info(`Scheduled task with pattern: ${this.cronPattern} in timezone: ${this.timezone}`);
|
|
727
|
+
}
|
|
728
|
+
job(path) {
|
|
729
|
+
log.info(`Scheduling job: ${path}`);
|
|
730
|
+
return this;
|
|
731
|
+
}
|
|
732
|
+
action(path) {
|
|
733
|
+
log.info(`Scheduling action: ${path}`);
|
|
734
|
+
return this;
|
|
735
|
+
}
|
|
736
|
+
static command(cmd) {
|
|
737
|
+
log.info(`Executing command: ${cmd}`);
|
|
738
|
+
return this;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
741
742
|
// src/index.ts
|
|
742
743
|
var src_default = Schedule;
|
|
743
744
|
export {
|
|
@@ -746,5 +747,5 @@ export {
|
|
|
746
747
|
src_default as default,
|
|
747
748
|
Schedule,
|
|
748
749
|
CronTime,
|
|
749
|
-
|
|
750
|
+
CronJob as BunCronJob
|
|
750
751
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/scheduler",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.61.1",
|
|
5
5
|
"description": "The Stacks scheduler.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
7
|
"license": "MIT",
|
|
@@ -54,9 +54,10 @@
|
|
|
54
54
|
"luxon": "^3.4.4"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@fast-check/jest": "^1.8.
|
|
57
|
+
"@fast-check/jest": "^1.8.1",
|
|
58
58
|
"@stacksjs/development": "latest",
|
|
59
|
+
"@types/luxon": "^3.4.2",
|
|
59
60
|
"@types/sinon": "^17.0.3",
|
|
60
|
-
"sinon": "^
|
|
61
|
+
"sinon": "^18.0.0"
|
|
61
62
|
}
|
|
62
63
|
}
|