/**
* Promise utility functions for bulk operations
*/
/**
* Runs promises in parallel with concurrency limit
*/
export async function parallelLimit<T, R>(
items: T[],
limit: number,
fn: (item: T) => Promise<R>
): Promise<R[]> {
const results: R[] = [];
const executing: Promise<void>[] = [];
for (const [index, item] of items.entries()) {
const promise = fn(item).then((result) => {
results[index] = result;
});
executing.push(promise);
if (executing.length >= limit) {
await Promise.race(executing);
executing.splice(
executing.findIndex((p) => p === promise),
1
);
}
}
await Promise.all(executing);
return results;
}
/**
* Runs promises with error isolation
*/
export async function settleAll<T>(
promises: Promise<T>[]
): Promise<
Array<
{ status: 'fulfilled'; value: T } | { status: 'rejected'; reason: unknown }
>
> {
return Promise.allSettled(promises);
}
/**
* Retry a promise with exponential backoff
*/
export async function retry<T>(
fn: () => Promise<T>,
options: {
maxRetries?: number;
delay?: number;
backoff?: number;
} = {}
): Promise<T> {
const { maxRetries = 3, delay = 1000, backoff = 2 } = options;
let lastError: unknown;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
if (attempt < maxRetries) {
await new Promise((resolve) =>
setTimeout(resolve, delay * Math.pow(backoff, attempt))
);
}
}
}
throw lastError;
}