From be3b6848661c40163c4b255020df2ee32b23b1aa Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Tue, 6 Feb 2018 10:20:11 +0100 Subject: [PATCH] feat(cron): better API (#40) --- @xen-orchestra/cron/README.md | 17 ++++---- @xen-orchestra/cron/src/index.js | 69 ++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/@xen-orchestra/cron/README.md b/@xen-orchestra/cron/README.md index 663209c0e..ef9913101 100644 --- a/@xen-orchestra/cron/README.md +++ b/@xen-orchestra/cron/README.md @@ -13,17 +13,20 @@ Installation of the [npm package](https://npmjs.org/package/@xen-orchestra/cron) ## Usage ```js -import * as Cron from '@xen-orchestra/cron' +import { createSchedule } from '@xen-orchestra/cron' -Cron.parse('* * * jan,mar *') -// → { month: [ 1, 3 ] } +const schedule = createSchedule('0 0 * * sun', 'America/New_York') -Cron.next('* * * jan,mar *', 2, 'America/New_York') -// → [ 2018-01-19T22:15:00.000Z, 2018-01-19T22:16:00.000Z ] +schedule.next(2) +// [ 2018-02-11T05:00:00.000Z, 2018-02-18T05:00:00.000Z ] -const stop = Cron.schedule('@hourly', () => { +const job = schedule.createJob(() => { console.log(new Date()) -}, 'UTC+05:30') +}) + +job.start() + +job.stop() ``` ### Pattern syntax diff --git a/@xen-orchestra/cron/src/index.js b/@xen-orchestra/cron/src/index.js index ac8154df5..dae5c62e8 100644 --- a/@xen-orchestra/cron/src/index.js +++ b/@xen-orchestra/cron/src/index.js @@ -1,40 +1,49 @@ import { DateTime } from 'luxon' -import nextDate from './next' +import next from './next' import parse from './parse' -const autoParse = pattern => - typeof pattern === 'string' ? parse(pattern) : schedule - -export const next = (cronPattern, n = 1, zone = 'utc') => { - const schedule = autoParse(cronPattern) - - let date = DateTime.fromObject({ zone }) - const dates = [] - for (let i = 0; i < n; ++i) { - dates.push((date = nextDate(schedule, date)).toJSDate()) - } - return dates -} - -export { parse } - -export const schedule = (cronPattern, fn, zone = 'utc') => { - const wrapper = () => { - fn() - scheduleNextRun() +class Job { + constructor (schedule, fn) { + const wrapper = scheduledRun => { + if (scheduledRun) { + fn() + } + this._timeout = setTimeout(wrapper, schedule.next() - Date.now(), true) + } + this._fn = wrapper + this._timeout = undefined } - let handle - const schedule = autoParse(cronPattern) - const scheduleNextRun = () => { - const now = DateTime.fromObject({ zone }) - const nextRun = next(schedule, now) - handle = setTimeout(wrapper, nextRun - now) + start () { + this.stop() + this._fn() } - scheduleNextRun() - return () => { - clearTimeout(handle) + stop () { + clearTimeout(this._timeout) } } + +class Schedule { + constructor (pattern, zone = 'utc') { + this._schedule = parse(pattern) + this._dateTimeOpts = { zone } + } + + createJob (fn) { + return new Job(this, fn) + } + + next (n) { + const dates = new Array(n) + const schedule = this._schedule + let date = DateTime.fromObject(this._dateTimeOpts) + for (let i = 0; i < n; ++i) { + dates[i] = (date = next(schedule, date)).toJSDate() + } + return dates + } +} + +export const createSchedule = (...args) => new Schedule(...args)