export interface GenerationPollingProcessor { processNext(): Promise; } export class GenerationPollingLoop { private closed = false; private inFlight = false; private readonly timer: ReturnType; constructor( private readonly processor: GenerationPollingProcessor, intervalMilliseconds = 250, ) { if (!Number.isSafeInteger(intervalMilliseconds) || intervalMilliseconds <= 0) { throw new Error("generation_polling_interval_invalid"); } this.timer = setInterval(() => this.run(), intervalMilliseconds); } close() { if (this.closed) return; this.closed = true; clearInterval(this.timer); } private run() { if (this.closed || this.inFlight) return; this.inFlight = true; void this.processor.processNext() .catch(() => undefined) .finally(() => { this.inFlight = false; }); } }