From 582a7df92b9b21631b19dc90c6c66f85d71243b4 Mon Sep 17 00:00:00 2001 From: Mariam Zakaria <123750992+mariam851@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:03:43 +0200 Subject: [PATCH] feat: implement pool() for controlled concurrency and add tests #1375 --- src/core.ts | 24 ++++++++++++++++++++++++ test/pool.test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 test/pool.test.js diff --git a/src/core.ts b/src/core.ts index 94acee83cb..35b68f8400 100644 --- a/src/core.ts +++ b/src/core.ts @@ -1085,3 +1085,27 @@ export function resolveDefaults( return m }, defs) } + +/** + * Runs tasks with limited concurrency. + * @param limit Max number of concurrent tasks. + * @param tasks Array of functions returning promises. + */ +export async function pool( + limit: number, + tasks: (() => Promise)[] +): Promise { + const results = new Array(tasks.length) + const queue = tasks.entries() + + const worker = async () => { + for (const [index, task] of queue) { + results[index] = await task() + } + } + + const workers = Array.from({ length: Math.min(limit, tasks.length) }, worker) + await Promise.all(workers) + + return results +} diff --git a/test/pool.test.js b/test/pool.test.js new file mode 100644 index 0000000000..4a874f7e73 --- /dev/null +++ b/test/pool.test.js @@ -0,0 +1,27 @@ +import { test } from 'node:test' +import assert from 'node:assert' +import { $, pool, within, quote } from '../src/index.ts' + +test('pool() limits concurrency', async () => { + await within(async () => { + $.quote = quote + $.shell = true + + console.log(' Running concurrency test...') + const start = Date.now() + const duration = 1000 + + await pool(2, [ + () => $`node -e "setTimeout(() => {}, ${duration})"`, + () => $`node -e "setTimeout(() => {}, ${duration})"`, + () => $`node -e "setTimeout(() => {}, ${duration})"`, + () => $`node -e "setTimeout(() => {}, ${duration})"`, + ]) + + const totalDuration = Date.now() - start + console.log(`Total time: ${totalDuration}ms`) + + assert.ok(totalDuration >= 2000, `Too fast! Got ${totalDuration}ms`) + assert.ok(totalDuration < 3500, `Too slow! Got ${totalDuration}ms`) + }) +})