2.9 KiB
preload.ts — bounded-concurrency bulk load
Purpose
This module implements the bounded-concurrency preload algorithm
backing IrLoader.preload. It launches up to concurrency workers (each
a while-loop that pops the next id off a shared cursor), threads the
caller's AbortSignal through every per-id load, and produces either a
fully-populated array of ImpulseResponse (in input order) on success
or an aggregate AUDIO_IR_LOADER.DECODE_FAILED error carrying every
per-id failure on partial failure.
Features
- Concurrency clamped to
[1, 32]to prevent caller mistakes from saturating the runtime. - Input order preserved on success — the
resultsarray is indexed by the id's position inids, not by completion order. - Aggregate failure: every failing id is collected before the throw, so callers get a complete picture rather than the first error.
- Abort threading: workers stop launching new loads as soon as
signal.abortedbecomes true; the throw isABORTEDnotDECODE_FAILED.
Usage: Basic
const irs = await loader.preload(
["club-a", "club-b", "club-c"],
{ concurrency: 2 }
);
Usage: Advanced
The aggregate carries every failure for ergonomic dashboards:
import {
AUDIO_IR_LOADER_CODES,
AudioIrLoaderError,
} from "@suaveplan/audio-ir-loader";
try {
await loader.preload(ids);
} catch (err) {
if (err instanceof AudioIrLoaderError && err.errors !== undefined) {
for (const { id, error } of err.errors) {
metrics.recordLoadFailure({ id, code: error.code });
}
}
throw err;
}
Best-effort callers that want to keep going past failures can call
Promise.allSettled(ids.map((id) => loader.load(id))) directly.
API Reference
runPreload(loadFn, ids, options?): Promise<readonly ImpulseResponse[]>
loadFn— the per-id load function (the loader's closure).ids: readonly string[]— input ids; order preserved on success.options.signal?: AbortSignal— shared abort.options.concurrency?: number— clamped to[1, 32], default4.
On full success returns a frozen ImpulseResponse[] in input order. On
partial failure throws AUDIO_IR_LOADER.DECODE_FAILED with the failure
list on errors. On signal abort throws AUDIO_IR_LOADER.ABORTED
(carrying any pre-abort failures on errors).
Implementation Notes
The worker pool is a simple "N parallel tasks, all draining a shared
cursor" pattern. The cursor is captured in takeNext() which also checks
abort state on entry, so a mid-flight abort halts every worker on its
next iteration. Non-SuaveplanError throwables are wrapped as
AUDIO_IR_LOADER.RESOLVE_FAILED before being added to the aggregate;
this preserves the invariant that every entry in errors[] is a
SuaveplanError (and therefore carries a stable .code). The success
result is Object.freezed so callers can't mutate the array in place.