diff options
author | eug-vs <eug-vs@keemail.me> | 2020-12-02 02:01:02 +0300 |
---|---|---|
committer | eug-vs <eug-vs@keemail.me> | 2020-12-02 02:01:02 +0300 |
commit | f6c5ac6632781d813a6e1f1ba957e7f9e4d70738 (patch) | |
tree | 3412c6723790e315bbb2f13731cce2bea88f7380 | |
parent | fe32a86c9d388d35e146d71a88c3bf19b022f669 (diff) | |
download | mongo-cronjob-f6c5ac6632781d813a6e1f1ba957e7f9e4d70738.tar.gz |
feat: add initial Scheduler class
-rw-r--r-- | lib/scheduler.ts | 68 |
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; + |