const { Types } = require('mongoose'); const { Service } = require('feathers-mongoose'); const _ = require('lodash'); const cron = require('cron'); const Bluebird = require('bluebird'); const Model = require('./event.model.js'); const handleAttendClassJob = require('../../handlers'); const CronJob = cron.CronJob; const handleTestJob = () => new Promise(res => setTimeout(res, 10000)); class Events extends Service { async setup(app, path) { this.jobs = []; await this.rescheduleMissedEvents(); 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) { const event = await this.Model.findById(id); try { event.start(); await handleAttendClassJob(event); return event.complete(); } catch (error) { event.fail(error); } } } module.exports = app => { app.use('/events', new Events({ Model })); };