type QueueInput = { paused: () => boolean bootstrap: () => Promise bootstrapInstance: (directory: string) => Promise | void } export function createRefreshQueue(input: QueueInput) { const queued = new Set() let root = false let running = false let timer: ReturnType | undefined const tick = () => new Promise((resolve) => setTimeout(resolve, 0)) const take = (count: number) => { if (queued.size === 0) return [] as string[] const items: string[] = [] for (const item of queued) { queued.delete(item) items.push(item) if (items.length >= count) break } return items } const schedule = () => { if (timer) return timer = setTimeout(() => { timer = undefined void drain() }, 0) } const push = (directory: string) => { if (!directory) return queued.add(directory) if (input.paused()) return schedule() } const refresh = () => { root = true if (input.paused()) return schedule() } async function drain() { if (running) return running = true try { while (true) { if (input.paused()) return if (root) { root = false await input.bootstrap() await tick() continue } const dirs = take(2) if (dirs.length === 0) return await Promise.all(dirs.map((dir) => input.bootstrapInstance(dir))) await tick() } } finally { running = false if (input.paused()) return if (root || queued.size) schedule() } } return { push, refresh, clear(directory: string) { queued.delete(directory) }, dispose() { if (!timer) return clearTimeout(timer) timer = undefined }, } }