@stacksjs/scheduler 0.64.5 → 0.65.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/dist/cron.d.ts +2 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -4
- package/dist/index.js.map +12 -32
- package/dist/schedule.d.ts +32 -0
- package/dist/types.d.ts +4 -0
- package/package.json +8 -24
- package/src/cron.ts +11 -0
- package/src/index.ts +3 -16
- package/src/schedule.ts +45 -23
- package/src/types.ts +3 -0
- package/src/constants.ts +0 -81
- package/src/errors.ts +0 -7
- package/src/job.ts +0 -280
- package/src/time.ts +0 -719
- package/src/types/cron.ts +0 -72
- package/src/types/utils.ts +0 -7
- package/src/utils.ts +0 -16
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { DateTime } from "luxon";
|
|
2
|
+
export declare class Schedule {
|
|
3
|
+
private cronPattern;
|
|
4
|
+
private timezone;
|
|
5
|
+
private readonly task;
|
|
6
|
+
constructor(task: () => void);
|
|
7
|
+
everySecond(): Schedule;
|
|
8
|
+
everyMinute(): Schedule;
|
|
9
|
+
everyTwoMinutes(): Schedule;
|
|
10
|
+
everyFiveMinutes(): Schedule;
|
|
11
|
+
everyTenMinutes(): Schedule;
|
|
12
|
+
everyThirtyMinutes(): Schedule;
|
|
13
|
+
everyHour(): Schedule;
|
|
14
|
+
everyDay(): Schedule;
|
|
15
|
+
hourly(): Schedule;
|
|
16
|
+
daily(): Schedule;
|
|
17
|
+
weekly(): Schedule;
|
|
18
|
+
monthly(): Schedule;
|
|
19
|
+
yearly(): Schedule;
|
|
20
|
+
onDays(days: number[]): Schedule;
|
|
21
|
+
at(time: string): Schedule;
|
|
22
|
+
setTimeZone(timezone: string): Schedule;
|
|
23
|
+
start(): void;
|
|
24
|
+
job(path: string): Schedule;
|
|
25
|
+
action(path: string): Schedule;
|
|
26
|
+
static command(cmd: string): Schedule;
|
|
27
|
+
}
|
|
28
|
+
export declare class Job extends Schedule {}
|
|
29
|
+
export declare function sendAt(cronTime: string | Date | DateTime): DateTime;
|
|
30
|
+
export declare function timeout(cronTime: string | Date | DateTime): number;
|
|
31
|
+
export type Scheduler = typeof Schedule;
|
|
32
|
+
export default Schedule;
|
package/dist/types.d.ts
ADDED
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/scheduler",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.65.0",
|
|
5
5
|
"description": "The Stacks scheduler.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
|
+
"contributors": ["Chris Breuer <chris@stacksjs.org>"],
|
|
7
8
|
"license": "MIT",
|
|
8
9
|
"funding": "https://github.com/sponsors/chrisbbreuer",
|
|
9
10
|
"homepage": "https://github.com/stacksjs/stacks/tree/main/storage/framework/core/scheduler#readme",
|
|
@@ -15,13 +16,7 @@
|
|
|
15
16
|
"bugs": {
|
|
16
17
|
"url": "https://github.com/stacksjs/stacks/issues"
|
|
17
18
|
},
|
|
18
|
-
"keywords": [
|
|
19
|
-
"scheduler",
|
|
20
|
-
"node-cron",
|
|
21
|
-
"jobs",
|
|
22
|
-
"bun",
|
|
23
|
-
"stacks"
|
|
24
|
-
],
|
|
19
|
+
"keywords": ["scheduler", "node-cron", "jobs", "bun", "stacks"],
|
|
25
20
|
"exports": {
|
|
26
21
|
".": {
|
|
27
22
|
"bun": "./src/index.ts",
|
|
@@ -34,27 +29,16 @@
|
|
|
34
29
|
},
|
|
35
30
|
"module": "dist/index.js",
|
|
36
31
|
"types": "dist/index.d.ts",
|
|
37
|
-
"
|
|
38
|
-
"Chris Breuer <chris@stacksjs.org>"
|
|
39
|
-
],
|
|
40
|
-
"files": [
|
|
41
|
-
"README.md",
|
|
42
|
-
"dist",
|
|
43
|
-
"src"
|
|
44
|
-
],
|
|
32
|
+
"files": ["README.md", "dist", "src"],
|
|
45
33
|
"scripts": {
|
|
46
|
-
"build": "bun
|
|
47
|
-
"typecheck": "bun
|
|
34
|
+
"build": "bun build.ts",
|
|
35
|
+
"typecheck": "bun tsc --noEmit",
|
|
48
36
|
"prepublishOnly": "bun run build"
|
|
49
37
|
},
|
|
50
38
|
"dependencies": {
|
|
51
|
-
"
|
|
39
|
+
"cron": "^3.1.7"
|
|
52
40
|
},
|
|
53
41
|
"devDependencies": {
|
|
54
|
-
"@
|
|
55
|
-
"@stacksjs/development": "latest",
|
|
56
|
-
"@types/luxon": "^3.4.2",
|
|
57
|
-
"@types/sinon": "^17.0.3",
|
|
58
|
-
"sinon": "^18.0.0"
|
|
42
|
+
"@stacksjs/development": "0.64.6"
|
|
59
43
|
}
|
|
60
44
|
}
|
package/src/cron.ts
ADDED
package/src/index.ts
CHANGED
|
@@ -1,20 +1,7 @@
|
|
|
1
|
-
export { Schedule } from './schedule'
|
|
1
|
+
// export { Schedule } from './schedule'
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
export { CronTime } from './time'
|
|
5
|
-
|
|
6
|
-
export type {
|
|
7
|
-
CronCallback,
|
|
8
|
-
CronCommand,
|
|
9
|
-
CronContext,
|
|
10
|
-
CronJobParams,
|
|
11
|
-
CronOnCompleteCallback,
|
|
12
|
-
CronOnCompleteCommand,
|
|
13
|
-
Ranges,
|
|
14
|
-
TimeUnit,
|
|
15
|
-
} from './types/cron'
|
|
16
|
-
|
|
17
|
-
export * from './types/utils'
|
|
3
|
+
export * from './cron'
|
|
18
4
|
export * from './schedule'
|
|
5
|
+
export * from './types'
|
|
19
6
|
|
|
20
7
|
// export default Schedule
|
package/src/schedule.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { log } from '@stacksjs/cli'
|
|
2
1
|
import type { DateTime } from 'luxon'
|
|
3
|
-
import {
|
|
4
|
-
import { CronTime } from './
|
|
2
|
+
import { log, runCommand } from '@stacksjs/cli'
|
|
3
|
+
import { CronJob, CronTime } from './'
|
|
5
4
|
|
|
6
5
|
export class Schedule {
|
|
7
6
|
private cronPattern = ''
|
|
@@ -13,62 +12,72 @@ export class Schedule {
|
|
|
13
12
|
this.task = task
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
everySecond() {
|
|
15
|
+
everySecond(): Schedule {
|
|
17
16
|
this.cronPattern = '* * * * * *'
|
|
18
17
|
return this
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
everyMinute() {
|
|
20
|
+
everyMinute(): Schedule {
|
|
22
21
|
this.cronPattern = '0 * * * * *'
|
|
23
22
|
return this
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
everyTwoMinutes() {
|
|
25
|
+
everyTwoMinutes(): Schedule {
|
|
27
26
|
this.cronPattern = '*/2 * * * * *'
|
|
28
27
|
return this
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
everyFiveMinutes() {
|
|
30
|
+
everyFiveMinutes(): Schedule {
|
|
32
31
|
this.cronPattern = '*/5 * * * *'
|
|
33
32
|
return this
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
everyTenMinutes() {
|
|
35
|
+
everyTenMinutes(): Schedule {
|
|
37
36
|
this.cronPattern = '*/10 * * * *'
|
|
38
37
|
return this
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
everyThirtyMinutes() {
|
|
40
|
+
everyThirtyMinutes(): Schedule {
|
|
42
41
|
this.cronPattern = '*/30 * * * *'
|
|
43
42
|
return this
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
everyHour(): Schedule {
|
|
47
46
|
this.cronPattern = '0 0 * * * *'
|
|
48
47
|
return this
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
everyDay(): Schedule {
|
|
52
51
|
this.cronPattern = '0 0 0 * * *'
|
|
53
52
|
return this
|
|
54
53
|
}
|
|
55
54
|
|
|
56
|
-
|
|
55
|
+
hourly(): Schedule {
|
|
56
|
+
this.cronPattern = '0 0 * * * *'
|
|
57
|
+
return this
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
daily(): Schedule {
|
|
61
|
+
this.cronPattern = '0 0 0 * * *'
|
|
62
|
+
return this
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
weekly(): Schedule {
|
|
57
66
|
this.cronPattern = '0 0 0 * * 0'
|
|
58
67
|
return this
|
|
59
68
|
}
|
|
60
69
|
|
|
61
|
-
monthly() {
|
|
70
|
+
monthly(): Schedule {
|
|
62
71
|
this.cronPattern = '0 0 0 1 * *'
|
|
63
72
|
return this
|
|
64
73
|
}
|
|
65
74
|
|
|
66
|
-
yearly() {
|
|
75
|
+
yearly(): Schedule {
|
|
67
76
|
this.cronPattern = '0 0 0 1 1 *'
|
|
68
77
|
return this
|
|
69
78
|
}
|
|
70
79
|
|
|
71
|
-
onDays(days: number[]) {
|
|
80
|
+
onDays(days: number[]): Schedule {
|
|
72
81
|
const dayPattern = days.join(',')
|
|
73
82
|
this.cronPattern = `0 0 0 * * ${dayPattern}`
|
|
74
83
|
return this
|
|
@@ -81,41 +90,54 @@ export class Schedule {
|
|
|
81
90
|
// return this
|
|
82
91
|
// }
|
|
83
92
|
|
|
84
|
-
at(time: string) {
|
|
93
|
+
at(time: string): Schedule {
|
|
85
94
|
// Assuming time is in "HH:MM" format
|
|
86
95
|
const [hour, minute] = time.split(':').map(Number)
|
|
87
96
|
this.cronPattern = `${minute} ${hour} * * *`
|
|
88
97
|
return this
|
|
89
98
|
}
|
|
90
99
|
|
|
91
|
-
setTimeZone(timezone: string) {
|
|
100
|
+
setTimeZone(timezone: string): Schedule {
|
|
92
101
|
this.timezone = timezone
|
|
93
102
|
return this
|
|
94
103
|
}
|
|
95
104
|
|
|
96
|
-
start() {
|
|
105
|
+
start(): void {
|
|
106
|
+
// eslint-disable-next-line no-new
|
|
97
107
|
new CronJob(this.cronPattern, this.task, null, true, this.timezone)
|
|
98
108
|
log.info(`Scheduled task with pattern: ${this.cronPattern} in timezone: ${this.timezone}`)
|
|
99
109
|
}
|
|
100
110
|
|
|
101
111
|
// job and action methods need to be added and they accept a path string param
|
|
102
|
-
job(path: string) {
|
|
112
|
+
job(path: string): Schedule {
|
|
103
113
|
log.info(`Scheduling job: ${path}`)
|
|
104
114
|
return this
|
|
105
115
|
}
|
|
106
116
|
|
|
107
|
-
action(path: string) {
|
|
117
|
+
action(path: string): Schedule {
|
|
108
118
|
log.info(`Scheduling action: ${path}`)
|
|
109
119
|
return this
|
|
110
120
|
}
|
|
111
121
|
|
|
112
|
-
static command(cmd: string) {
|
|
122
|
+
static command(cmd: string): Schedule {
|
|
113
123
|
log.info(`Executing command: ${cmd}`)
|
|
114
|
-
|
|
115
|
-
|
|
124
|
+
return new Schedule(async () => {
|
|
125
|
+
log.info(`Executing command: ${cmd}`)
|
|
126
|
+
|
|
127
|
+
const result = await runCommand(cmd)
|
|
128
|
+
|
|
129
|
+
if (result.isErr()) {
|
|
130
|
+
log.error(result.error)
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
log.info(result.value)
|
|
135
|
+
})
|
|
116
136
|
}
|
|
117
137
|
}
|
|
118
138
|
|
|
139
|
+
export class Job extends Schedule {}
|
|
140
|
+
|
|
119
141
|
export function sendAt(cronTime: string | Date | DateTime): DateTime {
|
|
120
142
|
return new CronTime(cronTime).sendAt()
|
|
121
143
|
}
|
package/src/types.ts
ADDED
package/src/constants.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
export const CONSTRAINTS = Object.freeze({
|
|
2
|
-
second: [0, 59],
|
|
3
|
-
minute: [0, 59],
|
|
4
|
-
hour: [0, 23],
|
|
5
|
-
dayOfMonth: [1, 31],
|
|
6
|
-
month: [1, 12],
|
|
7
|
-
dayOfWeek: [0, 7],
|
|
8
|
-
} as const)
|
|
9
|
-
export const MONTH_CONSTRAINTS = Object.freeze({
|
|
10
|
-
1: 31,
|
|
11
|
-
2: 29, // support leap year...not perfect
|
|
12
|
-
3: 31,
|
|
13
|
-
4: 30,
|
|
14
|
-
5: 31,
|
|
15
|
-
6: 30,
|
|
16
|
-
7: 31,
|
|
17
|
-
8: 31,
|
|
18
|
-
9: 30,
|
|
19
|
-
10: 31,
|
|
20
|
-
11: 30,
|
|
21
|
-
12: 31,
|
|
22
|
-
} as const)
|
|
23
|
-
export const PARSE_DEFAULTS = Object.freeze({
|
|
24
|
-
second: '0',
|
|
25
|
-
minute: '*',
|
|
26
|
-
hour: '*',
|
|
27
|
-
dayOfMonth: '*',
|
|
28
|
-
month: '*',
|
|
29
|
-
dayOfWeek: '*',
|
|
30
|
-
} as const)
|
|
31
|
-
export const ALIASES = Object.freeze({
|
|
32
|
-
jan: 1,
|
|
33
|
-
feb: 2,
|
|
34
|
-
mar: 3,
|
|
35
|
-
apr: 4,
|
|
36
|
-
may: 5,
|
|
37
|
-
jun: 6,
|
|
38
|
-
jul: 7,
|
|
39
|
-
aug: 8,
|
|
40
|
-
sep: 9,
|
|
41
|
-
oct: 10,
|
|
42
|
-
nov: 11,
|
|
43
|
-
dec: 12,
|
|
44
|
-
sun: 0,
|
|
45
|
-
mon: 1,
|
|
46
|
-
tue: 2,
|
|
47
|
-
wed: 3,
|
|
48
|
-
thu: 4,
|
|
49
|
-
fri: 5,
|
|
50
|
-
sat: 6,
|
|
51
|
-
} as const)
|
|
52
|
-
export const TIME_UNITS_MAP = Object.freeze({
|
|
53
|
-
SECOND: 'second',
|
|
54
|
-
MINUTE: 'minute',
|
|
55
|
-
HOUR: 'hour',
|
|
56
|
-
DAY_OF_MONTH: 'dayOfMonth',
|
|
57
|
-
MONTH: 'month',
|
|
58
|
-
DAY_OF_WEEK: 'dayOfWeek',
|
|
59
|
-
} as const)
|
|
60
|
-
export const TIME_UNITS = Object.freeze(Object.values(TIME_UNITS_MAP)) as [
|
|
61
|
-
'second',
|
|
62
|
-
'minute',
|
|
63
|
-
'hour',
|
|
64
|
-
'dayOfMonth',
|
|
65
|
-
'month',
|
|
66
|
-
'dayOfWeek',
|
|
67
|
-
]
|
|
68
|
-
export const TIME_UNITS_LEN: number = TIME_UNITS.length
|
|
69
|
-
export const PRESETS = Object.freeze({
|
|
70
|
-
'@yearly': '0 0 0 1 1 *',
|
|
71
|
-
'@monthly': '0 0 0 1 * *',
|
|
72
|
-
'@weekly': '0 0 0 * * 0',
|
|
73
|
-
'@daily': '0 0 0 * * *',
|
|
74
|
-
'@hourly': '0 0 * * * *',
|
|
75
|
-
'@minutely': '0 * * * * *',
|
|
76
|
-
'@secondly': '* * * * * *',
|
|
77
|
-
'@weekdays': '0 0 0 * * 1-5',
|
|
78
|
-
'@weekends': '0 0 0 * * 0,6',
|
|
79
|
-
} as const)
|
|
80
|
-
export const RE_WILDCARDS = /\*/g
|
|
81
|
-
export const RE_RANGE = /^(\d+)(?:-(\d+))?(?:\/(\d+))?$/g
|
package/src/errors.ts
DELETED
package/src/job.ts
DELETED
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Many thanks to https://github.com/kelektiv/node-cron for the inspiration
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { spawn } from 'node:child_process'
|
|
6
|
-
import { CronError, ExclusiveParametersError } from './errors'
|
|
7
|
-
import { CronTime } from './time'
|
|
8
|
-
import type {
|
|
9
|
-
CronCallback,
|
|
10
|
-
CronCommand,
|
|
11
|
-
CronContext,
|
|
12
|
-
CronJobParams,
|
|
13
|
-
CronOnCompleteCallback,
|
|
14
|
-
CronOnCompleteCommand,
|
|
15
|
-
WithOnComplete,
|
|
16
|
-
} from './types/cron'
|
|
17
|
-
import { getTimeZoneAndOffset } from './utils'
|
|
18
|
-
|
|
19
|
-
export class CronJob<OC extends CronOnCompleteCommand | null = null, C = null> {
|
|
20
|
-
cronTime: CronTime
|
|
21
|
-
running = false
|
|
22
|
-
unrefTimeout = false
|
|
23
|
-
lastExecution: Date | null = null
|
|
24
|
-
runOnce = false
|
|
25
|
-
context: CronContext<C>
|
|
26
|
-
onComplete?: WithOnComplete<OC> extends true ? CronOnCompleteCallback : undefined
|
|
27
|
-
|
|
28
|
-
private _timeout?: NodeJS.Timeout
|
|
29
|
-
private _callbacks: CronCallback<C, WithOnComplete<OC>>[] = []
|
|
30
|
-
private _errorHandler?: (error: Error) => void
|
|
31
|
-
|
|
32
|
-
constructor(
|
|
33
|
-
cronTime: CronJobParams<OC, C>['cronTime'],
|
|
34
|
-
onTick: CronJobParams<OC, C>['onTick'],
|
|
35
|
-
onComplete?: CronJobParams<OC, C>['onComplete'],
|
|
36
|
-
start?: CronJobParams<OC, C>['start'],
|
|
37
|
-
timeZone?: CronJobParams<OC, C>['timeZone'],
|
|
38
|
-
context?: CronJobParams<OC, C>['context'],
|
|
39
|
-
runOnInit?: CronJobParams<OC, C>['runOnInit'],
|
|
40
|
-
utcOffset?: null,
|
|
41
|
-
unrefTimeout?: CronJobParams<OC, C>['unrefTimeout'],
|
|
42
|
-
errorHandler?: (error: Error) => void,
|
|
43
|
-
)
|
|
44
|
-
constructor(
|
|
45
|
-
cronTime: CronJobParams<OC, C>['cronTime'],
|
|
46
|
-
onTick: CronJobParams<OC, C>['onTick'],
|
|
47
|
-
onComplete?: CronJobParams<OC, C>['onComplete'],
|
|
48
|
-
start?: CronJobParams<OC, C>['start'],
|
|
49
|
-
timeZone?: null,
|
|
50
|
-
context?: CronJobParams<OC, C>['context'],
|
|
51
|
-
runOnInit?: CronJobParams<OC, C>['runOnInit'],
|
|
52
|
-
utcOffset?: CronJobParams<OC, C>['utcOffset'],
|
|
53
|
-
unrefTimeout?: CronJobParams<OC, C>['unrefTimeout'],
|
|
54
|
-
errorHandler?: (error: Error) => void,
|
|
55
|
-
)
|
|
56
|
-
constructor(
|
|
57
|
-
cronTime: CronJobParams<OC, C>['cronTime'],
|
|
58
|
-
onTick: CronJobParams<OC, C>['onTick'],
|
|
59
|
-
onComplete?: CronJobParams<OC, C>['onComplete'],
|
|
60
|
-
start?: CronJobParams<OC, C>['start'],
|
|
61
|
-
timeZone?: CronJobParams<OC, C>['timeZone'],
|
|
62
|
-
context?: CronJobParams<OC, C>['context'],
|
|
63
|
-
runOnInit?: CronJobParams<OC, C>['runOnInit'],
|
|
64
|
-
utcOffset?: CronJobParams<OC, C>['utcOffset'],
|
|
65
|
-
unrefTimeout?: CronJobParams<OC, C>['unrefTimeout'],
|
|
66
|
-
errorHandler?: (error: Error) => void,
|
|
67
|
-
) {
|
|
68
|
-
this._errorHandler = errorHandler
|
|
69
|
-
this.context = (context ?? this) as CronContext<C>
|
|
70
|
-
|
|
71
|
-
const { timeZone: tz, utcOffset: uo } = getTimeZoneAndOffset(timeZone, utcOffset)
|
|
72
|
-
|
|
73
|
-
this.cronTime = new CronTime(cronTime, tz, uo as null | undefined)
|
|
74
|
-
|
|
75
|
-
if (unrefTimeout != null) this.unrefTimeout = unrefTimeout
|
|
76
|
-
|
|
77
|
-
if (onComplete != null) {
|
|
78
|
-
// casting to the correct type since we just made sure that WithOnComplete<OC> = true
|
|
79
|
-
this.onComplete = this._fnWrap(onComplete) as WithOnComplete<OC> extends true ? CronOnCompleteCallback : undefined
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (this.cronTime.realDate) this.runOnce = true
|
|
83
|
-
|
|
84
|
-
this.addCallback(this._fnWrap(onTick))
|
|
85
|
-
|
|
86
|
-
if (runOnInit) {
|
|
87
|
-
this.lastExecution = new Date()
|
|
88
|
-
this.fireOnTick()
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (start) this.start()
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
static from<OC extends CronOnCompleteCommand | null = null, C = null>(params: CronJobParams<OC, C>) {
|
|
95
|
-
// runtime check for JS users
|
|
96
|
-
if (params.timeZone != null && params.utcOffset != null) throw new ExclusiveParametersError('timeZone', 'utcOffset')
|
|
97
|
-
|
|
98
|
-
if (params.timeZone != null) {
|
|
99
|
-
return new CronJob<OC, C>(
|
|
100
|
-
params.cronTime,
|
|
101
|
-
params.onTick,
|
|
102
|
-
params.onComplete,
|
|
103
|
-
params.start,
|
|
104
|
-
params.timeZone,
|
|
105
|
-
params.context,
|
|
106
|
-
params.runOnInit,
|
|
107
|
-
params.utcOffset,
|
|
108
|
-
params.unrefTimeout,
|
|
109
|
-
)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (params.utcOffset != null) {
|
|
113
|
-
return new CronJob<OC, C>(
|
|
114
|
-
params.cronTime,
|
|
115
|
-
params.onTick,
|
|
116
|
-
params.onComplete,
|
|
117
|
-
params.start,
|
|
118
|
-
null,
|
|
119
|
-
params.context,
|
|
120
|
-
params.runOnInit,
|
|
121
|
-
params.utcOffset,
|
|
122
|
-
params.unrefTimeout,
|
|
123
|
-
)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return new CronJob<OC, C>(
|
|
127
|
-
params.cronTime,
|
|
128
|
-
params.onTick,
|
|
129
|
-
params.onComplete,
|
|
130
|
-
params.start,
|
|
131
|
-
params.timeZone,
|
|
132
|
-
params.context,
|
|
133
|
-
params.runOnInit,
|
|
134
|
-
params.utcOffset,
|
|
135
|
-
params.unrefTimeout,
|
|
136
|
-
)
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private _fnWrap(cmd: CronCommand<C, boolean>): CronCallback<C, boolean> {
|
|
140
|
-
switch (typeof cmd) {
|
|
141
|
-
case 'function': {
|
|
142
|
-
return cmd
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
case 'string': {
|
|
146
|
-
const [command, ...args] = cmd.split(' ')
|
|
147
|
-
|
|
148
|
-
return spawn.bind(undefined, command ?? cmd, args, {}) as () => void
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
case 'object': {
|
|
152
|
-
return spawn.bind(undefined, cmd.command, cmd.args ?? [], cmd.options ?? {}) as () => void
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
addCallback(callback: CronCallback<C, WithOnComplete<OC>>) {
|
|
158
|
-
if (typeof callback === 'function') this._callbacks.push(callback)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
setTime(time: CronTime) {
|
|
162
|
-
if (!(time instanceof CronTime)) throw new CronError('time must be an instance of CronTime.')
|
|
163
|
-
|
|
164
|
-
const wasRunning = this.running
|
|
165
|
-
this.stop()
|
|
166
|
-
|
|
167
|
-
this.cronTime = time
|
|
168
|
-
if (time.realDate) this.runOnce = true
|
|
169
|
-
|
|
170
|
-
if (wasRunning) this.start()
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
nextDate() {
|
|
174
|
-
return this.cronTime.sendAt()
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
fireOnTick() {
|
|
178
|
-
try {
|
|
179
|
-
for (const callback of this._callbacks) {
|
|
180
|
-
void callback.call(
|
|
181
|
-
this.context,
|
|
182
|
-
this.onComplete as WithOnComplete<OC> extends true ? CronOnCompleteCallback : never,
|
|
183
|
-
)
|
|
184
|
-
}
|
|
185
|
-
} catch (error) {
|
|
186
|
-
if (this._errorHandler && error instanceof Error) {
|
|
187
|
-
this._errorHandler(error)
|
|
188
|
-
} else {
|
|
189
|
-
// Handle the case where no error handler is provided or the caught object is not an Error
|
|
190
|
-
console.error('An error occurred in the cron job callback:', error)
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
nextDates(i?: number) {
|
|
196
|
-
return this.cronTime.sendAt(i ?? 0)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
start() {
|
|
200
|
-
if (this.running) return
|
|
201
|
-
|
|
202
|
-
const MAXDELAY = 2147483647 // The maximum number of milliseconds setTimeout will wait.
|
|
203
|
-
let timeout = this.cronTime.getTimeout()
|
|
204
|
-
let remaining = 0
|
|
205
|
-
let startTime: number
|
|
206
|
-
|
|
207
|
-
const setCronTimeout = (t: number) => {
|
|
208
|
-
this._timeout = setTimeout(callbackWrapper, t) as NodeJS.Timeout
|
|
209
|
-
if (this.unrefTimeout && typeof this._timeout.unref === 'function') this._timeout.unref()
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// The callback wrapper checks if it needs to sleep another period or not
|
|
213
|
-
// and does the real callback logic when it’s time.
|
|
214
|
-
const callbackWrapper = () => {
|
|
215
|
-
const diff = startTime + timeout - Date.now()
|
|
216
|
-
|
|
217
|
-
if (diff > 0) {
|
|
218
|
-
let newTimeout = this.cronTime.getTimeout()
|
|
219
|
-
|
|
220
|
-
if (newTimeout > diff) newTimeout = diff
|
|
221
|
-
|
|
222
|
-
remaining += newTimeout
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// If there is sleep time remaining, calculate how long and go to sleep
|
|
226
|
-
// again. This processing might make us miss the deadline by a few ms
|
|
227
|
-
// times the number of sleep sessions. Given a MAXDELAY of almost a
|
|
228
|
-
// month, this should be no issue.
|
|
229
|
-
if (remaining) {
|
|
230
|
-
if (remaining > MAXDELAY) {
|
|
231
|
-
remaining -= MAXDELAY
|
|
232
|
-
timeout = MAXDELAY
|
|
233
|
-
} else {
|
|
234
|
-
timeout = remaining
|
|
235
|
-
remaining = 0
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
setCronTimeout(timeout)
|
|
239
|
-
} else {
|
|
240
|
-
// We have arrived at the correct point in time.
|
|
241
|
-
this.lastExecution = new Date()
|
|
242
|
-
|
|
243
|
-
this.running = false
|
|
244
|
-
|
|
245
|
-
// start before calling back so the callbacks have the ability to stop the cron job
|
|
246
|
-
if (!this.runOnce) this.start()
|
|
247
|
-
|
|
248
|
-
this.fireOnTick()
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (timeout >= 0) {
|
|
253
|
-
this.running = true
|
|
254
|
-
|
|
255
|
-
// Don't try to sleep more than MAXDELAY ms at a time.
|
|
256
|
-
|
|
257
|
-
if (timeout > MAXDELAY) {
|
|
258
|
-
remaining = timeout - MAXDELAY
|
|
259
|
-
timeout = MAXDELAY
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
setCronTimeout(timeout)
|
|
263
|
-
} else {
|
|
264
|
-
this.stop()
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
lastDate() {
|
|
269
|
-
return this.lastExecution
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Stop the cronjob.
|
|
274
|
-
*/
|
|
275
|
-
stop() {
|
|
276
|
-
if (this._timeout) clearTimeout(this._timeout)
|
|
277
|
-
this.running = false
|
|
278
|
-
if (typeof this.onComplete === 'function') void this.onComplete.call(this.context)
|
|
279
|
-
}
|
|
280
|
-
}
|