/** Bound parallel DB reads so large rosters do not create unbounded fan-out. */ export async function readBatches( items: readonly T[], load: (batch: T[]) => PromiseLike, batchSize = 100, concurrency = 4, ): Promise { if (!Number.isInteger(batchSize) || batchSize < 1 || !Number.isInteger(concurrency) || concurrency < 1) throw new Error("Invalid batch configuration"); const output: R[] = []; for (let offset = 0; offset < items.length; offset += batchSize * concurrency) { const group: PromiseLike[] = []; for (let cursor = offset; cursor < Math.min(items.length, offset + batchSize * concurrency); cursor += batchSize) { group.push(load(items.slice(cursor, cursor + batchSize))); } for (const rows of await Promise.all(group)) output.push(...rows); } return output; }