packages/cdk/lib/cloudquery/schedule.ts (48 lines of code) (raw):

import type { Schedule } from 'aws-cdk-lib/aws-events'; import awsCronParser from 'aws-cron-parser'; /** * Takes a schedule and figures out its frequency. Supports both CRON and RATE schedules. * * @param schedule - An AWS EventBridge Schedule * @returns the duration in milliseconds between executions */ export const scheduleFrequencyMs = (schedule: Schedule): number => { // RATE and CRON are both 4 characters long const type = schedule.expressionString.substring(0, 4); const expression = schedule.expressionString.substring( 5, schedule.expressionString.length - 1, ); switch (type) { case 'rate': return scheduleFromRate(expression); case 'cron': return scheduleFromCron(expression); default: throw new Error(`Unexpected schedule type: ${type}`); } }; /** * Parse a AWS EventBridge RATE expression, eg. `rate(4 hours)` * @param expression * @returns period between executions in milliseconds */ const scheduleFromRate = (expression: string): number => { // Parse the RATE type of schedule, eg `rate(5 hours)` const [amountString, type] = expression.split(' '); const typeInMilliseconds: Record<string, number> = { days: 24 * 60 * 60 * 1000, hours: 60 * 60 * 1000, minutes: 60 * 1000, seconds: 1000, }; if (type === undefined || amountString === undefined) { throw new Error(`Malformed Rate expression: ${expression}`); } const typeMultiplier = typeInMilliseconds[type] ?? typeInMilliseconds[`${type}s`]; const amount = parseInt(amountString); if (typeMultiplier === undefined) { throw new Error(`Unexpected rate type: ${expression}`); } return typeMultiplier * amount; }; /** * Parse a AWS EventBridge CRON expression, eg. `cron(* * * 4 * *)` * @param expression * @returns period between executions in milliseconds */ const scheduleFromCron = (expression: string): number => { // AWS uses a non-standard CRON expression so we need to rely on a cron library specifically designed // for parsing AWS cron expressions. const parsedExpression = awsCronParser.parse(expression); const occurrence = awsCronParser.next(parsedExpression, new Date()); if (!occurrence) { throw new Error(`First occurrence of schedule not found: ${expression}`); } const nextOccurrence = awsCronParser.next(parsedExpression, occurrence); if (!nextOccurrence) { throw new Error(`Second occurrence of schedule not found: ${expression}`); } return nextOccurrence.getTime() - occurrence.getTime(); };