Files
openclaw/src/plugin-sdk/keyed-async-queue.ts
2026-03-02 20:55:15 +00:00

49 lines
1.1 KiB
TypeScript

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 } : {}),
});
}
}