File size: 1,167 Bytes
fc93158 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | export type KeyedAsyncQueueHooks = {
onEnqueue?: () => void;
onSettle?: () => void;
};
export function enqueueKeyedTask<T>(params: {
tails: Map<string, Promise<void>>;
key: string;
task: () => Promise<T>;
hooks?: KeyedAsyncQueueHooks;
}): Promise<T> {
params.hooks?.onEnqueue?.();
const previous = params.tails.get(params.key) ?? Promise.resolve();
const current = previous
.catch(() => undefined)
.then(params.task)
.finally(() => {
params.hooks?.onSettle?.();
});
const tail = current.then(
() => undefined,
() => undefined,
);
params.tails.set(params.key, tail);
void tail.finally(() => {
if (params.tails.get(params.key) === tail) {
params.tails.delete(params.key);
}
});
return current;
}
export class KeyedAsyncQueue {
private readonly tails = new Map<string, Promise<void>>();
getTailMapForTesting(): Map<string, Promise<void>> {
return this.tails;
}
enqueue<T>(key: string, task: () => Promise<T>, hooks?: KeyedAsyncQueueHooks): Promise<T> {
return enqueueKeyedTask({
tails: this.tails,
key,
task,
...(hooks ? { hooks } : {}),
});
}
}
|