import { CorePluginSignatures , MiniflareCore , ReloadEvent , logResponse , } from "@miniflare/core" ; import type { Cron , ITimerHandle } from "cron-schedule" ; import { SchedulerPlugin } from "./plugin" ; export * from "./plugin" ; export interface CronSchedulerImpl { setInterval ( cron , task ) : ITimerHandle ; clearTimeoutOrInterval ( handle ) : void ; } export type SchedulerPluginSignatures = CorePluginSignatures & { SchedulerPlugin : typeof SchedulerPlugin ; } ; const kReload = Symbol ( "kReload" ) ; export class CronScheduler < Plugins extends SchedulerPluginSignatures > { private previousValidatedCrons ? : Cron [ ] ; private scheduledHandles ? : ITimerHandle [ ] ; constructor ( private readonly mf , private readonly cronScheduler = Promise . resolve ( ) . then ( ( ) => require ( "cron-schedule" ) . TimerBasedCronScheduler ) ) { mf . addEventListener ( "reload" , this [ kReload ] ) ; } [ kReload ] = async ( event ) : Promise < void > => { const validatedCrons = event . plugins . SchedulerPlugin . validatedCrons ; if ( this . previousValidatedCrons === validatedCrons ) return ; this . previousValidatedCrons = validatedCrons ; const cronScheduler = await this . cronScheduler ; this . scheduledHandles ?. forEach ( ( handle ) => cronScheduler . clearTimeoutOrInterval ( handle ) ) ; if ( ! validatedCrons . length ) return ; this . scheduledHandles = validatedCrons ?. map ( ( cron ) => { const spec = cron . toString ( ) ; return cronScheduler . setInterval ( cron , async ( ) => { const start = process . hrtime ( ) ; const waitUntil = this . mf . dispatchScheduled ( undefined , spec ) ; await logResponse ( this . mf . log , { start , method : "SCHD" , url : spec , waitUntil , } ) ; } ) ; } ) ; } ; async dispose ( ) { this . mf . removeEventListener ( "reload" , this [ kReload ] ) ; const cronScheduler = await this . cronScheduler ; this . scheduledHandles ?. forEach ( ( handle ) => cronScheduler . clearTimeoutOrInterval ( handle ) ) ; } } export async function startScheduler < Plugins extends SchedulerPluginSignatures > ( mf , cronScheduler ? ) { const scheduler = new CronScheduler ( mf , cronScheduler ) ; const reloadEvent = new ReloadEvent ( "reload" , { plugins : await mf . getPlugins ( ) , initial : false , } ) ; await scheduler [ kReload ] ( reloadEvent ) ; return scheduler ; }