@@ -218,6 +218,132 @@ describe('Test Pulse', () => {
218218 test ( 'returns itself' , ( ) => {
219219 expect ( globalPulseInstance . resumeOnRestart ( false ) ) . toEqual ( globalPulseInstance ) ;
220220 } ) ;
221+
222+ test ( 'should not reschedule successfully finished non-recurring jobs' , async ( ) => {
223+ const job = globalPulseInstance . create ( 'sendEmail' , { to : 'user@example.com' } ) ;
224+ job . attrs . lastFinishedAt = new Date ( ) ;
225+ job . attrs . nextRunAt = null ;
226+ await job . save ( ) ;
227+
228+ await globalPulseInstance . resumeOnRestart ( ) ;
229+
230+ const updatedJob = ( await globalPulseInstance . jobs ( { name : 'sendEmail' } ) ) [ 0 ] ;
231+ expect ( updatedJob . attrs . nextRunAt ) . toBeNull ( ) ;
232+ } ) ;
233+
234+ test ( 'should resume non-recurring jobs on restart' , async ( ) => {
235+ const job = globalPulseInstance . create ( 'sendEmail' , { to : 'user@example.com' } ) ;
236+ job . attrs . nextRunAt = new Date ( Date . now ( ) - 1000 ) ;
237+ await job . save ( ) ;
238+
239+ await globalPulseInstance . resumeOnRestart ( ) ;
240+
241+ const updatedJob = ( await globalPulseInstance . jobs ( { name : 'sendEmail' } ) ) [ 0 ] ;
242+ expect ( updatedJob . attrs . nextRunAt ?. getTime ( ) ) . toBeGreaterThan ( Date . now ( ) - 100 ) ;
243+ } ) ;
244+
245+ test ( 'should resume recurring jobs on restart - interval' , async ( ) => {
246+ const job = globalPulseInstance . create ( 'sendEmail' , { to : 'user@example.com' } ) ;
247+ job . attrs . repeatInterval = '5 minutes' ;
248+ job . attrs . nextRunAt = null ;
249+ await job . save ( ) ;
250+
251+ await globalPulseInstance . resumeOnRestart ( ) ;
252+
253+ const updatedJob = ( await globalPulseInstance . jobs ( { name : 'sendEmail' } ) ) [ 0 ] ;
254+ expect ( updatedJob . attrs . nextRunAt ) . not . toBeNull ( ) ;
255+ } ) ;
256+
257+ test ( 'should resume recurring jobs on restart - cron' , async ( ) => {
258+ const job = globalPulseInstance . create ( 'sendEmail' , { to : 'user@example.com' } ) ;
259+ job . attrs . repeatInterval = '*/5 * * * *' ;
260+ job . attrs . nextRunAt = null ;
261+ await job . save ( ) ;
262+
263+ await globalPulseInstance . resumeOnRestart ( ) ;
264+
265+ const updatedJob = ( await globalPulseInstance . jobs ( { name : 'sendEmail' } ) ) [ 0 ] ;
266+ expect ( updatedJob . attrs . nextRunAt ) . not . toBeNull ( ) ;
267+ } ) ;
268+
269+ test ( 'should resume recurring jobs on restart - repeatAt' , async ( ) => {
270+ const job = globalPulseInstance . create ( 'sendEmail' , { to : 'user@example.com' } ) ;
271+ job . attrs . repeatAt = '1:00 am' ;
272+ job . attrs . nextRunAt = null ;
273+ await job . save ( ) ;
274+
275+ await globalPulseInstance . resumeOnRestart ( ) ;
276+
277+ const updatedJob = ( await globalPulseInstance . jobs ( { name : 'sendEmail' } ) ) [ 0 ] ;
278+ expect ( updatedJob . attrs . nextRunAt ) . not . toBeNull ( ) ;
279+ } ) ;
280+
281+ test ( 'should not modify jobs with existing nextRunAt' , async ( ) => {
282+ const futureDate = new Date ( Date . now ( ) + 60 * 60 * 1000 ) ;
283+ const job = globalPulseInstance . create ( 'sendEmail' , { to : 'user@example.com' } ) ;
284+ job . attrs . nextRunAt = futureDate ;
285+ await job . save ( ) ;
286+
287+ await globalPulseInstance . resumeOnRestart ( ) ;
288+
289+ const updatedJob = ( await globalPulseInstance . jobs ( { name : 'sendEmail' } ) ) [ 0 ] ;
290+ expect ( updatedJob . attrs . nextRunAt ?. getTime ( ) ) . toEqual ( futureDate . getTime ( ) ) ;
291+ } ) ;
292+
293+ test ( 'should handle jobs that started but have not finished (non-recurring)' , async ( ) => {
294+ const job = globalPulseInstance . create ( 'processData' , { data : 'sample' } ) ;
295+ job . attrs . nextRunAt = null ;
296+ job . attrs . lockedAt = new Date ( ) ;
297+ await job . save ( ) ;
298+
299+ await globalPulseInstance . resumeOnRestart ( ) ;
300+
301+ const updatedJob = ( await globalPulseInstance . jobs ( { name : 'processData' } ) ) [ 0 ] ;
302+
303+ const now = Date . now ( ) ;
304+ expect ( updatedJob . attrs . nextRunAt ) . not . toBeNull ( ) ;
305+ expect ( updatedJob . attrs . nextRunAt ?. getTime ( ) ) . toBeGreaterThan ( now - 100 ) ;
306+ } ) ;
307+
308+ test ( 'should handle recurring jobs that started but have not finished' , async ( ) => {
309+ const job = globalPulseInstance . create ( 'processData' , { data : 'sample' } ) ;
310+ job . attrs . repeatInterval = '10 minutes' ;
311+ job . attrs . lockedAt = new Date ( ) ;
312+ job . attrs . nextRunAt = new Date ( Date . now ( ) + 10000 ) ;
313+ await job . save ( ) ;
314+
315+ await globalPulseInstance . resumeOnRestart ( ) ;
316+
317+ const updatedJob = ( await globalPulseInstance . jobs ( { name : 'processData' } ) ) [ 0 ] ;
318+ expect ( updatedJob . attrs . lockedAt ) . not . toBeNull ( ) ;
319+ expect ( updatedJob . attrs . nextRunAt ) . not . toBeNull ( ) ;
320+ } ) ;
321+
322+ test ( 'should handle interrupted recurring jobs after server recovery' , async ( ) => {
323+ const job = globalPulseInstance . create ( 'processData' , { data : 'sample' } ) ;
324+ job . attrs . repeatInterval = '5 minutes' ;
325+ job . attrs . lastModifiedBy = 'server_crash' ;
326+ job . attrs . nextRunAt = null ;
327+ await job . save ( ) ;
328+
329+ await globalPulseInstance . resumeOnRestart ( ) ;
330+
331+ const updatedJob = ( await globalPulseInstance . jobs ( { name : 'processData' } ) ) [ 0 ] ;
332+ expect ( updatedJob . attrs . nextRunAt ) . not . toBeNull ( ) ;
333+ expect ( updatedJob . attrs . lastModifiedBy ) . not . toEqual ( 'server_crash' ) ;
334+ } ) ;
335+
336+ test ( 'should not modify non-recurring jobs with lastFinishedAt in the past' , async ( ) => {
337+ const job = globalPulseInstance . create ( 'sendEmail' , { to : 'user@example.com' } ) ;
338+ job . attrs . lastFinishedAt = new Date ( Date . now ( ) - 10000 ) ;
339+ job . attrs . nextRunAt = null ;
340+ await job . save ( ) ;
341+
342+ await globalPulseInstance . resumeOnRestart ( ) ;
343+
344+ const updatedJob = ( await globalPulseInstance . jobs ( { name : 'sendEmail' } ) ) [ 0 ] ;
345+ expect ( updatedJob . attrs . nextRunAt ) . toBeNull ( ) ;
346+ } ) ;
221347 } ) ;
222348 } ) ;
223349
0 commit comments