@@ -32,7 +32,8 @@ export interface CronJobOptions {
32
32
export class CronJob < RootContext = unknown > extends EventEmitter {
33
33
// state
34
34
application : string
35
- tasks : Record < string , _TaskExecutor >
35
+ #tasks: Record < string , _TaskExecutor >
36
+ #deleted: Record < string , boolean >
36
37
nextTick : null | NodeJS . Timeout
37
38
isDestroyed : boolean
38
39
isLocked : boolean
@@ -47,7 +48,8 @@ export class CronJob<RootContext = unknown> extends EventEmitter {
47
48
constructor ( options : CronJobOptions ) {
48
49
super ( )
49
50
this . application = options . application
50
- this . tasks = { }
51
+ this . #tasks = { }
52
+ this . #deleted = { }
51
53
this . nextTick = null
52
54
this . isDestroyed = false
53
55
this . isLocked = false
@@ -69,7 +71,7 @@ export class CronJob<RootContext = unknown> extends EventEmitter {
69
71
if ( this . isDestroyed ) return ''
70
72
// we need to prefix uid
71
73
! uid . startsWith ( 'interval-' ) && ( uid = `interval-${ uid } ` )
72
- this . tasks [ uid ] = async ( ) => {
74
+ this . # tasks[ uid ] = async ( ) => {
73
75
try {
74
76
await executor ( ( context ?? this . #context) as Context )
75
77
} catch ( err ) {
@@ -93,7 +95,7 @@ export class CronJob<RootContext = unknown> extends EventEmitter {
93
95
if ( this . isDestroyed ) return ''
94
96
// we need to prefix uid
95
97
! uid . startsWith ( 'timeout-' ) && ( uid = `timeout-${ uid } ` )
96
- this . tasks [ uid ] = async ( ) => {
98
+ this . # tasks[ uid ] = async ( ) => {
97
99
try {
98
100
await executor ( ( context ?? this . #context) as Context )
99
101
} catch ( err ) {
@@ -116,7 +118,7 @@ export class CronJob<RootContext = unknown> extends EventEmitter {
116
118
if ( this . isDestroyed ) return ''
117
119
// we need to prefix uid
118
120
! uid . startsWith ( 'immediate-' ) && ( uid = `immediate-${ uid } ` )
119
- this . tasks [ uid ] = async ( ) => {
121
+ this . # tasks[ uid ] = async ( ) => {
120
122
try {
121
123
await executor ( ( context ?? this . #context) as Context )
122
124
} catch ( err ) {
@@ -136,43 +138,71 @@ export class CronJob<RootContext = unknown> extends EventEmitter {
136
138
cron : string ,
137
139
uid : string ,
138
140
context ?: Context
141
+ ) : Promise < string > {
142
+ return await this . #setCronJob( executor , cron , uid , true , context )
143
+ }
144
+
145
+ async #setCronJob< Context = RootContext > (
146
+ executor : TaskExecutor < Context > ,
147
+ cron : string ,
148
+ uid : string ,
149
+ fresh : boolean ,
150
+ context ?: Context
139
151
) : Promise < string > {
140
152
const nextExecuteAt = Number ( parseExpression ( cron ) . next ( ) . toDate ( ) )
141
153
const ms = nextExecuteAt - Date . now ( )
154
+ const _uid = `timeout-cron-${ uid } `
155
+ if ( fresh ) this . #deleted[ _uid ] = false
156
+ if ( this . #deleted[ _uid ] ) return ''
142
157
143
158
return await this . setTimeout ( async ( context ) => {
159
+ if ( this . #deleted[ _uid ] ) return
144
160
setImmediate ( ( ) => {
145
161
// we execute immediately for the next task
146
162
Promise . race ( [
147
163
executor ( context ) ,
148
- this . setCronJob ( executor , cron , uid , context )
164
+ this . # setCronJob( executor , cron , uid , false , context )
149
165
] ) . catch ( ( err ) => {
150
166
this . emit ( 'error' , err )
151
167
} )
152
168
} )
153
- } , ms , `timeout-cron- ${ uid } ` , context )
169
+ } , ms , _uid , context )
154
170
}
155
171
156
172
async setLoopTask < Context = RootContext > (
157
173
executor : TaskExecutor < Context > ,
158
174
uid : string ,
159
175
context ?: Context
160
176
) : Promise < string > {
177
+ return await this . #setLoopTask( executor , uid , true , context )
178
+ }
179
+
180
+ async #setLoopTask< Context = RootContext > (
181
+ executor : TaskExecutor < Context > ,
182
+ uid : string ,
183
+ fresh : boolean ,
184
+ context ?: Context
185
+ ) : Promise < string > {
186
+ const _uid = `immediate-loop-${ uid } `
187
+ if ( fresh ) this . #deleted[ _uid ] = false
188
+ if ( this . #deleted[ _uid ] ) return ''
161
189
return await this . setImmediate ( async ( context ) => {
190
+ if ( this . #deleted[ _uid ] ) return
162
191
try {
163
192
await executor ( context )
164
193
} finally {
165
- await this . setLoopTask ( executor , uid , context )
194
+ await this . # setLoopTask( executor , uid , false , context )
166
195
}
167
- } , `timeout-loop- ${ uid } ` , context )
196
+ } , _uid , context )
168
197
}
169
198
170
199
clearInterval ( uid : string ) : void {
200
+ this . #deleted[ uid ] = true
171
201
this . #deleteTask( uid )
172
202
}
173
203
174
204
clearTimeout ( uid : string ) : void {
175
- this . #deleteTask ( uid )
205
+ this . clearInterval ( uid )
176
206
}
177
207
178
208
async #_deleteTask ( uid : string ) : Promise < void > {
@@ -228,7 +258,7 @@ export class CronJob<RootContext = unknown> extends EventEmitter {
228
258
await this . adapter . updateTask ( task . uid , executeAt , task . once )
229
259
}
230
260
231
- const executor = this . tasks [ task . uid ]
261
+ const executor = this . # tasks[ task . uid ]
232
262
if ( typeof executor !== 'function' ) {
233
263
// when we missing runtime
234
264
// we delay the task to maxExecutionMS
0 commit comments