Skip to content

Commit

Permalink
Extend schedule event support
Browse files Browse the repository at this point in the history
  • Loading branch information
dnalborczyk committed Nov 24, 2019
1 parent abac840 commit 1c29984
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 45 deletions.
114 changes: 69 additions & 45 deletions src/events/schedule/Schedule.js
Original file line number Diff line number Diff line change
@@ -1,73 +1,45 @@
// 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 {
constructor(lambda) {
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)
Expand All @@ -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)
}
Expand Down
13 changes: 13 additions & 0 deletions src/events/schedule/ScheduleEventData.js
Original file line number Diff line number Diff line change
@@ -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
}
}

0 comments on commit 1c29984

Please sign in to comment.