import { Instance } from "../project/instance" import { Log } from "../util/log" export namespace Scheduler { const log = Log.create({ service: "scheduler" }) export type Task = { id: string interval: number run: () => Promise scope?: "instance" | "global" } type Timer = ReturnType type Entry = { tasks: Map timers: Map } const create = (): Entry => { const tasks = new Map() const timers = new Map() return { tasks, timers } } const shared = create() const state = Instance.state( () => create(), async (entry) => { for (const timer of entry.timers.values()) { clearInterval(timer) } entry.tasks.clear() entry.timers.clear() }, ) export function register(task: Task) { const scope = task.scope ?? "instance" const entry = scope === "global" ? shared : state() const current = entry.timers.get(task.id) if (current && scope === "global") return if (current) clearInterval(current) entry.tasks.set(task.id, task) void run(task) const timer = setInterval(() => { void run(task) }, task.interval) timer.unref() entry.timers.set(task.id, timer) } async function run(task: Task) { log.info("run", { id: task.id }) await task.run().catch((error) => { log.error("run failed", { id: task.id, error }) }) } }