async function limitConcurrency( factories: Array<() => Promise>, maxConcurrency: number ): Promise[]> { if (factories.length === 0) { return []; } if (maxConcurrency <= 0 || maxConcurrency >= factories.length) { return Promise.allSettled(factories.map((f) => f())); } const results: Array | undefined> = new Array(factories.length).fill(undefined); let nextIndex = 0; const worker = async () => { while (nextIndex < factories.length) { const index = nextIndex++; try { const value = await factories[index](); results[index] = { status: "fulfilled", value }; } catch (reason) { results[index] = { status: "rejected", reason }; } } }; const workers = Array(Math.min(maxConcurrency, factories.length)).fill(null).map(() => worker()); await Promise.all(workers); return results as PromiseSettledResult[]; } function delay(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } describe("Parallel Execution", () => { describe("limitConcurrency", () => { it("returns empty array for zero factories", async () => { const results = await limitConcurrency([], 5); expect(results).toEqual([]); }); it("returns single-element result for one factory", async () => { const results = await limitConcurrency([() => Promise.resolve(42)], 5); expect(results).toHaveLength(1); expect(results[0].status).toBe("fulfilled"); if (results[0].status === "fulfilled") { expect(results[0].value).toBe(42); } }); it("behaves sequentially when maxConcurrency=1", async () => { const order: number[] = []; const factories = [1, 2, 3].map((n) => () => delay(30).then(() => { order.push(n); return n; }) ); const start = Date.now(); const results = await limitConcurrency(factories, 1); const elapsed = Date.now() - start; expect(results).toHaveLength(3); for (const r of results) { expect(r.status).toBe("fulfilled"); } expect(order).toEqual([1, 2, 3]); expect(elapsed).toBeGreaterThanOrEqual(80); }); it("runs concurrently when maxConcurrency exceeds factory count", async () => { const factories = ["a", "b"].map((v) => () => delay(50).then(() => v) ); const start = Date.now(); const results = await limitConcurrency(factories, 10); const elapsed = Date.now() - start; expect(results).toHaveLength(2); expect(elapsed).toBeLessThan(120); }); it("limits to maxConcurrency=2 with 4 factories", async () => { const timestamps: number[] = []; const factories = [0, 1, 2, 3].map((i) => () => delay(80).then(() => { timestamps.push(i); return i; }) ); const start = Date.now(); const results = await limitConcurrency(factories, 2); const elapsed = Date.now() - start; expect(results).toHaveLength(4); for (const r of results) { expect(r.status).toBe("fulfilled"); if (r.status === "fulfilled") { expect([0, 1, 2, 3]).toContain(r.value); } } expect(elapsed).toBeGreaterThanOrEqual(150); expect(elapsed).toBeLessThan(350); }); it("isolates rejected promises from fulfilled ones", async () => { const factories = [ () => Promise.resolve("success"), () => Promise.reject(new Error("boom")), () => Promise.resolve("also-success"), ]; const results = await limitConcurrency(factories, 5); expect(results).toHaveLength(3); const fulfilled = results.filter((r) => r.status === "fulfilled"); const rejected = results.filter((r) => r.status === "rejected"); expect(fulfilled).toHaveLength(2); expect(rejected).toHaveLength(1); if (fulfilled[0].status === "fulfilled") { expect(fulfilled[0].value).toBe("success"); } if (fulfilled[1].status === "fulfilled") { expect(fulfilled[1].value).toBe("also-success"); } if (rejected[0].status === "rejected") { expect((rejected[0].reason as Error).message).toBe("boom"); } }); it("handles maxConcurrency=0 as no limit", async () => { const factories = [1, 2, 3].map((v) => () => Promise.resolve(v)); const results = await limitConcurrency(factories, 0); expect(results).toHaveLength(3); for (const r of results) { expect(r.status).toBe("fulfilled"); } }); }); describe("parallel vs sequential timing", () => { it("parallel execution is faster than sequential", async () => { const DELAY_MS = 50; const parallelFactories = [DELAY_MS, DELAY_MS].map((ms) => () => delay(ms)); const parallelStart = Date.now(); const parallelResults = await limitConcurrency(parallelFactories, 5); const parallelElapsed = Date.now() - parallelStart; const sequentialStart = Date.now(); for (const ms of [DELAY_MS, DELAY_MS]) { await delay(ms); } const sequentialElapsed = Date.now() - sequentialStart; expect(parallelResults).toHaveLength(2); expect(parallelElapsed).toBeLessThan(sequentialElapsed); expect(parallelElapsed).toBeLessThan(DELAY_MS * 1.8); }); }); describe("concurrency limit verification", () => { it("at most maxConcurrency agents run simultaneously", async () => { let concurrentCount = 0; let maxConcurrent = 0; const MAX = 2; const factories = [0, 1, 2, 3].map( (i) => () => new Promise((resolve) => { concurrentCount++; if (concurrentCount > maxConcurrent) maxConcurrent = concurrentCount; delay(60).then(() => { concurrentCount--; resolve(i); }); }) ); const results = await limitConcurrency(factories, MAX); expect(results).toHaveLength(4); expect(maxConcurrent).toBeLessThanOrEqual(MAX); }); }); describe("sequential fallback behavior", () => { it("runs agents in order when parallelization disabled", async () => { const executionOrder: string[] = []; await (async () => { for (const name of ["code-reviewer", "security-auditor"]) { executionOrder.push(`start:${name}`); await delay(10); executionOrder.push(`end:${name}`); } })(); expect(executionOrder).toEqual([ "start:code-reviewer", "end:code-reviewer", "start:security-auditor", "end:security-auditor", ]); }); }); describe("single agent edge case", () => { it("no review agents means no parallel code path triggered", async () => { const results = await limitConcurrency([], 5); expect(results).toHaveLength(0); }); }); });