• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

node-cron / node-cron / 14765410028

30 Apr 2025 10:16PM UTC coverage: 91.876% (-2.0%) from 93.838%
14765410028

push

github

merencia
adding features

524 of 618 branches covered (84.79%)

Branch coverage included in aggregate %.

35 of 81 new or added lines in 3 files covered. (43.21%)

10 existing lines in 4 files now uncovered.

1783 of 1893 relevant lines covered (94.19%)

29186.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.02
/src/basic-scheduled-task.ts
1
'use strict';
16!
2

1✔
3
import EventEmitter from 'events';
1✔
4
import { ScheduledTask, CronEvent, Options } from './types';
1✔
5
import Scheduler from './scheduler';
1✔
6
import { randomUUID } from 'crypto';
1✔
7
import * as storage from './storage';
1✔
8

1✔
9
class BasicScheduledTask extends EventEmitter implements ScheduledTask {
1✔
10
    options: Options;
1✔
11
    status: string;
1✔
12
    func: Function;
1✔
13
    scheduler: Scheduler;
1✔
14
    executionCount: number;
1✔
15

1✔
16
    constructor(cronExpression: string, func: Function, options?: Options) {
1✔
17
        super();
16✔
18
        options = Object.assign({
16✔
19
          scheduled: true,
16✔
20
          catchUp: false
16✔
21
        }, options);
16✔
22
      
16✔
23
        this.options = options;
16✔
24
        this.options.name = this.options.name || randomUUID();
16✔
25

16✔
26
        this.status = 'stopped';
16✔
27

16✔
28
        this.func = func;
16✔
29
        this.scheduler = new Scheduler(cronExpression, options.timezone, options.catchUp);
16✔
30

16✔
31
        this.scheduler.on('scheduled-time-matched', (event) => {
16✔
32
            this.execute(event);
20✔
33
        });
16✔
34

16✔
35
        if(options.scheduled !== false){
16✔
36
            this.start();
10✔
37
        }
10✔
38
        
16✔
39
        if(options.runOnStart === true){
16✔
40
          this.execute({
1✔
41
            date: new Date(),
1✔
42
            dateLocalIso: this.scheduler.toLocalizedIso(new Date()),
1✔
43
            missedCount: 0,
1✔
44
            reason: 'initial'
1✔
45
          });
1✔
46
        }
1✔
47

16✔
48
        this.executionCount = 0;
16✔
49
    }
16✔
50
    
1✔
51
     async execute(event?: CronEvent): Promise<any> {
1✔
52
        if(this.options.noOverlap && this.status === 'running'){
22!
NEW
53
          this.emit('task-already-running', this)
×
NEW
54
          return;
×
NEW
55
        }
×
56

22✔
57
        if (this.options.maxExecutions && this.executionCount >= this.options.maxExecutions - 1) {
22!
UNCOV
58
          this.emit('task-execution-limit-reached');
×
UNCOV
59
          this.destroy();
×
UNCOV
60
        }
×
61

22✔
62
        if (!event){
22✔
63
            const date = new Date();
1✔
64
            event = {
1✔
65
                date: date,
1✔
66
                dateLocalIso: this.scheduler.toLocalizedIso(date),
1✔
67
                missedCount: 0,
1✔
68
                reason: 'manual'
1✔
69
            };
1✔
70
        }
1✔
71
        event.task = this;
22✔
72

22✔
73
        const previousStatus = this.status;
22✔
74
        this.status = 'running';
22✔
75
        this.emit('task-started', event);
22✔
76
        this.executionCount += 1;
22✔
77

22✔
78
        try {
22✔
79
          const result = await this.func(event);
22✔
80
          this.emit('task-done', result);
22✔
81
          if(previousStatus === 'stopped'){
22✔
82
            this.status = 'stopped';
2✔
83
          } else {
22✔
84
            this.status = 'idle';
19✔
85
          }
19✔
86
        } catch (error){
22✔
87
          if(previousStatus === 'stopped'){
1!
NEW
88
            this.status = 'stopped';
×
89
          } else {
1✔
90
            this.status = 'idle';
1✔
91
          }
1✔
92
          this.emit('task-error', event, error)
1✔
93
          if (this.options.onError){
1!
94
            this.options.onError(error);
×
95
          } else {
1✔
96
            throw error;
1✔
97
          }
1✔
98
        }
1✔
99
    }
22✔
100
    
1✔
101
    start() {
1✔
102
      if (this.status === 'destroyed') {
13!
103
        throw new Error('Task has been destroyed!');
×
UNCOV
104
      }
×
105

13✔
106
      if(this.status === 'stopped') {
13✔
107
        this.status = 'idle';
12✔
108
        this.scheduler.start();
12✔
109
        this.emit('scheduler-started');
12✔
110
      }
12✔
111
    }
13✔
112
    
1✔
113
    stop() {
1✔
114
        this.status = 'stopped';
13✔
115
        this.scheduler.stop();
13✔
116
        this.emit('scheduler-stopped');
13✔
117
    }
13✔
118

1✔
119
    getStatus() {
1✔
UNCOV
120
        return this.status;
×
UNCOV
121
    }
×
122

1✔
123
    destroy() {
1✔
124
        this.stop();
2✔
125
        this.status = 'destroyed';
2✔
126
        this.scheduler.removeAllListeners();
2✔
127
        storage.remove(this.options.name);
2✔
128
        this.emit('scheduler-destroyed');
2✔
129
    }
2✔
130
}
1✔
131

1✔
132
export default BasicScheduledTask;
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc