test(usage): make recorder.settled robust to nested waitUntil

Promise.all(pending) snapshotted the array at call time, missing the
inner ctx.waitUntil(sendToAxiom(...)) that emitUsageEvents pushes after
the outer drain begins. Tests passed only because the fetch spy resolved
in an earlier microtask tick. Replace with a quiescence loop so the
helper survives any future async in the emit path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sebastien Melki
2026-04-25 16:09:32 +03:00
parent 53d295f176
commit 24d511e29c

View File

@@ -31,15 +31,25 @@ interface CapturedEvent {
tier: number;
}
function makeRecordingCtx(): { ctx: GatewayCtx; settled: Promise<void[]> } {
function makeRecordingCtx(): { ctx: GatewayCtx; settled: Promise<void> } {
const pending: Promise<unknown>[] = [];
const ctx: GatewayCtx = {
waitUntil: (p) => { pending.push(p); },
};
// Quiescence loop: emitUsageEvents calls ctx.waitUntil from inside an
// already-pending waitUntil promise, so the array grows during drain.
// Keep awaiting until no new entries appear between iterations.
async function settled(): Promise<void> {
let prev = -1;
while (pending.length !== prev) {
prev = pending.length;
await Promise.allSettled(pending.slice(0, prev));
}
}
return {
ctx,
get settled() { return Promise.all(pending) as Promise<void[]>; },
} as { ctx: GatewayCtx; settled: Promise<void[]> };
get settled() { return settled(); },
} as { ctx: GatewayCtx; settled: Promise<void> };
}
function installAxiomFetchSpy(