export class Semaphore { private current = 0; private readonly waiting: Array<() => void> = []; constructor(private readonly limit: number) {} get active(): number { return this.current; } get queued(): number { return this.waiting.length; } async use(task: () => Promise): Promise { await this.acquire(); try { return await task(); } finally { this.release(); } } private async acquire(): Promise { if (this.current < this.limit) { this.current += 1; return; } await new Promise((resolve) => { this.waiting.push(() => { this.current += 1; resolve(); }); }); } private release(): void { this.current -= 1; const next = this.waiting.shift(); next?.(); } }