diff --git a/src/events/schedule/Schedule.js b/src/events/schedule/Schedule.js index 4dba0ef99..5bd851d13 100644 --- a/src/events/schedule/Schedule.js +++ b/src/events/schedule/Schedule.js @@ -1,10 +1,12 @@ // based on: // https://github.com/ajmath/serverless-offline-scheduler -// https://github.com/Meemaw/serverless-offline-schedule import nodeSchedule from 'node-schedule' +import ScheduleEventData from './ScheduleEventData.js' import { createUniqueId } from '../../utils/index.js' +// const CRON_LENGTH_WITH_YEAR = 6 + const { stringify } = JSON export default class Schedule { @@ -12,62 +14,32 @@ export default class Schedule { this._lambda = lambda } - _convertExpressionToCron(scheduleRate) { - if (scheduleRate.startsWith('cron(')) { - return scheduleRate.replace('cron(', '').replace(')', '') - } - - if (scheduleRate.startsWith('rate(')) { - const params = scheduleRate.replace('rate(', '').replace(')', '') - return this._convertRateToCron(params) - } - - throw new Error(`Invalid schedule rate: '${scheduleRate}'`) - } - - _convertRateToCron(rate) { - const [number, unit] = rate.split(' ') - - if (!unit) { - throw new Error(`Invalid rate format: '${rate}'`) - } - - if (unit.startsWith('minute')) { - return `*/${number} * * * *` - } - - if (unit.startsWith('hour')) { - return `0 */${number} * * *` - } + _scheduleEvent(functionKey, rawScheduleEvent) { + const scheduleEvent = new ScheduleEventData( + /* functionKey, */ rawScheduleEvent, + ) - if (unit.startsWith('day')) { - return `0 0 */${number} * *` - } + const { enabled, input, rate } = scheduleEvent - throw new Error(`Invalid rate format: '${rate}'`) - } + if (!enabled) { + console.log(`Scheduling [${functionKey}] cron: disabled`) - _scheduleEvent(functionKey, schedule) { - let cron - let event - - if (typeof schedule === 'string') { - cron = schedule - } else { - ;({ cron, input: event } = schedule) + return } - const cronValue = this._convertExpressionToCron(cron) + const cron = this._convertExpressionToCron(rate) console.log( - `Scheduling [${functionKey}] cron: [${cron}] input: ${stringify(event)}`, + `Scheduling [${functionKey}] cron: [${cron}] input: ${stringify( + scheduleEvent.input, + )}`, ) - nodeSchedule.scheduleJob(cronValue, async () => { + nodeSchedule.scheduleJob(cron, async () => { try { const lambdaFunction = this._lambda.get(functionKey) - lambdaFunction.setEvent(event) + lambdaFunction.setEvent(input) const requestId = createUniqueId() lambdaFunction.setRequestId(requestId) @@ -94,6 +66,58 @@ export default class Schedule { }) } + // _convertCronSyntax(cronString) { + // if (cronString.split(' ').length < CRON_LENGTH_WITH_YEAR) { + // return cronString + // } + // + // return cronString.replace(/\s\S+$/, '') + // } + + _convertRateToCron(rate) { + const [number, unit] = rate.split(' ') + + switch (unit) { + case 'minute': + case 'minutes': + return `*/${number} * * * *` + + case 'hour': + case 'hours': + return `0 */${number} * * *` + + case 'day': + case 'days': + return `0 0 */${number} * *` + + default: + console.log( + `scheduler: Invalid rate syntax '${rate}', will not schedule`, + ) + return null + } + } + + _convertExpressionToCron(scheduleEvent) { + const params = scheduleEvent + .replace('rate(', '') + .replace('cron(', '') + .replace(')', '') + + if (scheduleEvent.startsWith('cron(')) { + console.log('schedule rate "cron" not yet supported!') + // return this._convertCronSyntax(params) + } + + if (scheduleEvent.startsWith('rate(')) { + return this._convertRateToCron(params) + } + + console.log('scheduler: invalid, schedule syntax') + + return undefined + } + createEvent(functionKey, schedule) { this._scheduleEvent(functionKey, schedule) } diff --git a/src/events/schedule/ScheduleEventData.js b/src/events/schedule/ScheduleEventData.js new file mode 100644 index 000000000..d45d8d949 --- /dev/null +++ b/src/events/schedule/ScheduleEventData.js @@ -0,0 +1,13 @@ +export default class ScheduleEventData { + constructor(/* functionKey, */ rawEvent) { + const { description, enabled, input, name, rate } = + typeof rawEvent === 'string' ? {} : rawEvent + + this.description = description + // default if not specified: enabled + this.enabled = enabled == null ? true : enabled + this.input = input + this.name = name // ? || functionKey + this.rate = rate + } +}