Add awaitAll

This commit is contained in:
Andras Schmelczer 2025-11-23 15:22:50 +00:00
parent ef4444afc2
commit d8058d396c
8 changed files with 100 additions and 17 deletions

View file

@ -0,0 +1,56 @@
import { test } from "node:test";
import assert from "node:assert";
import { awaitAll } from "./await-all";
void test("awaitAll resolves promises of the same type", async () => {
const promises = [
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3)
];
const results = await awaitAll(promises);
assert.deepStrictEqual(results, [1, 2, 3]);
});
void test("awaitAll resolves promises of different types", async () => {
const promises = [
Promise.resolve("hello"),
Promise.resolve(42),
Promise.resolve(true)
] as const;
const results = await awaitAll(promises);
// Type assertions to verify type inference
const str: string = results[0];
const num: number = results[1];
const bool: boolean = results[2];
assert.strictEqual(str, "hello");
assert.strictEqual(num, 42);
assert.strictEqual(bool, true);
});
void test("awaitAll throws on first rejection", async () => {
const error = new Error("Test error");
const promises = [
Promise.resolve(1),
Promise.reject(error),
Promise.resolve(3)
];
await assert.rejects(async () => {
await awaitAll(promises);
}, error);
});
void test("awaitAll works with async functions", async () => {
const asyncString = async (): Promise<string> => "async";
const asyncNumber = async (): Promise<number> => 123;
const results = await awaitAll([asyncString(), asyncNumber()]);
assert.strictEqual(results[0], "async");
assert.strictEqual(results[1], 123);
});

View file

@ -0,0 +1,22 @@
type PromiseTuple<T extends readonly unknown[]> = readonly [
...{ [K in keyof T]: Promise<T[K]> }
];
type ResolvedTuple<T extends readonly unknown[]> = {
[K in keyof T]: T[K];
};
export const awaitAll = async <T extends readonly unknown[]>(
promises: PromiseTuple<T>
): Promise<ResolvedTuple<T>> => {
const result = await Promise.allSettled(promises);
for (const res of result) {
if (res.status === "rejected") {
throw res.reason;
}
}
return result.map(
(res) => (res as PromiseFulfilledResult<unknown>).value
) as ResolvedTuple<T>;
};

View file

@ -1,4 +1,5 @@
import type { Logger } from "../../tracing/logger";
import { awaitAll } from "../await-all";
/**
* Manages exclusive locks on items to prevent concurrent modifications.
@ -54,9 +55,7 @@ export class Locks<T> {
const uniqueKeys = Array.from(new Set(keys));
uniqueKeys.sort((a, b) => String(a).localeCompare(String(b))); // Ensure consistent order to prevent deadlocks
await Promise.allSettled(
uniqueKeys.map(async (key) => this.waitForLock(key))
);
await awaitAll(uniqueKeys.map(async (key) => this.waitForLock(key)));
try {
return await fn();