-
Notifications
You must be signed in to change notification settings - Fork 73
/
scheduler.orchestrator.ts
123 lines (104 loc) · 3.3 KB
/
scheduler.orchestrator.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import {
Injectable,
OnApplicationBootstrap,
OnApplicationShutdown,
} from '@nestjs/common';
import { CronCallback, CronJob, CronJobParams } from 'cron';
import { v4 } from 'uuid';
import { CronOptions } from './decorators/cron.decorator';
import { SchedulerRegistry } from './scheduler.registry';
type TargetHost = { target: Function };
type TimeoutHost = { timeout: number };
type RefHost<T> = { ref?: T };
type CronOptionsHost = {
options: CronOptions & Record<'cronTime', CronJobParams['cronTime']>;
};
type IntervalOptions = TargetHost & TimeoutHost & RefHost<number>;
type TimeoutOptions = TargetHost & TimeoutHost & RefHost<number>;
type CronJobOptions = TargetHost & CronOptionsHost & RefHost<CronJob>;
@Injectable()
export class SchedulerOrchestrator
implements OnApplicationBootstrap, OnApplicationShutdown {
private readonly cronJobs: Record<string, CronJobOptions> = {};
private readonly timeouts: Record<string, TimeoutOptions> = {};
private readonly intervals: Record<string, IntervalOptions> = {};
constructor(private readonly schedulerRegistry: SchedulerRegistry) {}
onApplicationBootstrap() {
this.mountTimeouts();
this.mountIntervals();
this.mountCron();
}
onApplicationShutdown() {
this.clearTimeouts();
this.clearIntervals();
this.closeCronJobs();
}
mountIntervals() {
const intervalKeys = Object.keys(this.intervals);
intervalKeys.forEach((key) => {
const options = this.intervals[key];
const intervalRef = setInterval(options.target, options.timeout);
options.ref = intervalRef;
this.schedulerRegistry.addInterval(key, intervalRef);
});
}
mountTimeouts() {
const timeoutKeys = Object.keys(this.timeouts);
timeoutKeys.forEach((key) => {
const options = this.timeouts[key];
const timeoutRef = setTimeout(options.target, options.timeout);
options.ref = timeoutRef;
this.schedulerRegistry.addTimeout(key, timeoutRef);
});
}
mountCron() {
const cronKeys = Object.keys(this.cronJobs);
cronKeys.forEach((key) => {
const { options, target } = this.cronJobs[key];
const cronJob = CronJob.from({
...options,
onTick: target as CronCallback<null, false>,
start: !options.disabled
});
this.cronJobs[key].ref = cronJob;
this.schedulerRegistry.addCronJob(key, cronJob);
});
}
clearTimeouts() {
this.schedulerRegistry.getTimeouts().forEach((key) =>
this.schedulerRegistry.deleteTimeout(key),
);
}
clearIntervals() {
this.schedulerRegistry.getIntervals().forEach((key) =>
this.schedulerRegistry.deleteInterval(key),
);
}
closeCronJobs() {
Array.from(this.schedulerRegistry.getCronJobs().keys()).forEach((key) =>
this.schedulerRegistry.deleteCronJob(key),
);
}
addTimeout(methodRef: Function, timeout: number, name: string = v4()) {
this.timeouts[name] = {
target: methodRef,
timeout,
};
}
addInterval(methodRef: Function, timeout: number, name: string = v4()) {
this.intervals[name] = {
target: methodRef,
timeout,
};
}
addCron(
methodRef: Function,
options: CronOptions & Record<'cronTime', CronJobParams['cronTime']>,
) {
const name = options.name || v4();
this.cronJobs[name] = {
target: methodRef,
options,
};
}
}