interface Args { cron: string job: (fireDate: Date) => Promise onError?: (err: any) => Promise | unknown invokeNow?: true } export async function schedule(args: Args) { const nodeSchedule: typeof import('node-schedule') = require('node-schedule') let lock = false let runAfter = false const errorCallback = args.onError ?? ((err: any) => console.error(err)) const call = async (fireDate: Date, skipLock?: true) => { if (lock === true && skipLock !== true) { runAfter = true return } lock = true await args.job(fireDate).catch(errorCallback) if (runAfter === true) { runAfter = false return setImmediate(() => call(new Date(), true)) } lock = false } const scheduled = nodeSchedule.scheduleJob(args.cron, call) if (args.invokeNow === true) { scheduled.invoke() } return scheduled }