perf(metadata): bound bulk re-enrich concurrency

A large batch selection fired hundreds of simultaneous requests (each also
enqueuing a worker job). Run them in batches of BULK_CONCURRENCY.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Цвылев Александр Вадимович
2026-07-29 10:53:49 +03:00
parent 5b31e77b1e
commit 22f7fd25ff
@@ -65,6 +65,23 @@ function fieldStyle(): React.CSSProperties {
return { width: '100%' }; return { width: '100%' };
} }
// Cap how many bulk metadata ops run at once — a large selection would otherwise
// fire hundreds of simultaneous requests (each also spins up a worker enqueue).
const BULK_CONCURRENCY = 6;
async function settleInBatches<T>(
items: T[],
limit: number,
op: (item: T) => Promise<unknown>,
): Promise<PromiseSettledResult<unknown>[]> {
const results: PromiseSettledResult<unknown>[] = [];
for (let i = 0; i < items.length; i += limit) {
const batch = items.slice(i, i + limit);
results.push(...(await Promise.allSettled(batch.map(op))));
}
return results;
}
/** /**
* `/tracks/:trackId/metadata` — A7 metadata editor: manual edits + AcoustID * `/tracks/:trackId/metadata` — A7 metadata editor: manual edits + AcoustID
* match picker with a current-vs-proposed diff. `/metadata/batch` operates on a * match picker with a current-vs-proposed diff. `/metadata/batch` operates on a
@@ -723,7 +740,7 @@ function BatchEditor() {
setBusy(true); setBusy(true);
setResult(null); setResult(null);
const ids = [...selected]; const ids = [...selected];
const outcomes = await Promise.allSettled(ids.map(op)); const outcomes = await settleInBatches(ids, BULK_CONCURRENCY, op);
const ok = outcomes.filter((o) => o.status === 'fulfilled').length; const ok = outcomes.filter((o) => o.status === 'fulfilled').length;
setResult({ ok, fail: ids.length - ok }); setResult({ ok, fail: ids.length - ok });
setBusy(false); setBusy(false);