aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eug-vs@keemail.me>2020-12-02 02:01:02 +0300
committereug-vs <eug-vs@keemail.me>2020-12-02 02:01:02 +0300
commitf6c5ac6632781d813a6e1f1ba957e7f9e4d70738 (patch)
tree3412c6723790e315bbb2f13731cce2bea88f7380
parentfe32a86c9d388d35e146d71a88c3bf19b022f669 (diff)
downloadmongo-cronjob-f6c5ac6632781d813a6e1f1ba957e7f9e4d70738.tar.gz
feat: add initial Scheduler class
-rw-r--r--lib/scheduler.ts68
1 files changed, 68 insertions, 0 deletions
diff --git a/lib/scheduler.ts b/lib/scheduler.ts
new file mode 100644
index 0000000..449ac39
--- /dev/null
+++ b/lib/scheduler.ts
@@ -0,0 +1,68 @@
+import cron from 'cron';
+import Bluebird from 'bluebird';
+import { EventModel } from './model';
+
+const CronJob = cron.CronJob;
+
+class Scheduler {
+ jobs: cron.CronJob[];
+ Model: EventModel<any>;
+
+ constructor(model: EventModel<any>) {
+ this.Model = model;
+ this.jobs = [];
+
+ const job = new CronJob('*/10 * * * * *', () => this.updateJobs());
+ job.start();
+ }
+
+ startAllJobs() {
+ this.jobs.forEach(job => job.start());
+ }
+
+ stopAllJobs() {
+ this.jobs.forEach(job => job.stop());
+ }
+
+ async rescheduleMissedEvents() {
+ const missedEvents = await this.Model.findMissedEvents();
+ return Bluebird.map(missedEvents, event => event.save());
+ }
+
+ async updateJobs() {
+ // Reschedule missed events before we stop jobs to avoid
+ // accidentally stopping the job that has not triggered yet
+ // (if event schedule resonates with updateJobs schedule)
+ await this.rescheduleMissedEvents();
+
+ this.stopAllJobs();
+
+ const events = await this.Model.findNextEvents();
+ if (!events.length) console.log('WARNING: no upcoming events');
+ this.jobs = events.map(event => new CronJob(
+ event.schedule,
+ () => this.run(event.id)
+ ));
+
+ this.startAllJobs();
+ }
+
+ async run(id: string) {
+ const event = await this.Model.findById(id);
+ // TODO: handle the case when event is deleted
+ if (!event) return;
+
+ try {
+ event.start();
+ // TODO: put actual handler here
+ await new Promise(res => setTimeout(res, 5000));
+ return event.complete();
+ } catch (error) {
+ event.fail(error);
+ }
+ }
+}
+
+
+export default Scheduler;
+