Shaheer Sarfaraz aefb6ca78b
feat(orchestrator): parallelize scoring and bulk rescore with bounded concurrency (#194)
* feat(orchestrator): parallelize scoring and bulk rescore with bounded concurrency

* chore(docs): format versioned docs metadata for biome

* fix(orchestrator): address PR review feedback on async pool and bulk rescore

* ci(docs): run biome --write before docs version commit
2026-02-19 18:32:13 +00:00

39 lines
1.1 KiB
TypeScript

export async function asyncPool<TItem, TResult>(args: {
items: readonly TItem[];
concurrency: number;
shouldStop?: () => boolean;
task: (item: TItem, index: number) => Promise<TResult>;
}): Promise<TResult[]> {
const { items, task, shouldStop } = args;
const rawConcurrency = Number.isFinite(args.concurrency)
? args.concurrency
: 1;
const safeConcurrency = Math.max(1, Math.min(10, Math.floor(rawConcurrency)));
if (items.length === 0) return [];
const UNSET = Symbol("unset");
const results: Array<TResult | typeof UNSET> = Array.from(
{ length: items.length },
() => UNSET,
);
let nextIndex = 0;
const worker = async (): Promise<void> => {
while (true) {
if (shouldStop?.()) return;
const currentIndex = nextIndex;
nextIndex += 1;
if (currentIndex >= items.length) return;
results[currentIndex] = await task(items[currentIndex], currentIndex);
}
};
const workerCount = Math.min(safeConcurrency, items.length);
await Promise.all(Array.from({ length: workerCount }, () => worker()));
return results.filter((value): value is TResult => value !== UNSET);
}