feat(server): add racePeering helper with tests

Exports `racePeering(origin, timeoutMs, ensurePeeredFn?)` that races
`ensurePeered` against a deadline. On timeout, the background handshake
continues (warming the peer for the next attempt) and a warn-logged
.catch() prevents unhandledRejection. Injectable `ensurePeeredFn` param
enables full DI in tests without mocking module internals.
This commit is contained in:
Jannis Braun
2026-04-21 13:37:30 +02:00
parent 1be544bbd5
commit b22a7bd0c6
2 changed files with 83 additions and 1 deletions
@@ -210,3 +210,38 @@ async function performHandshake(
export function _clearInFlightPeering(): void {
inFlightPeering.clear();
}
/**
* Race ensurePeered() against a deadline. On timeout, the background
* handshake is NOT aborted — it continues so the next attempt finds
* the peer active. A warn-logged catch is attached so a late-rejecting
* background promise does not emit an unhandledRejection.
*
* The ensurePeered implementation is injectable for testing; the default
* is the real function.
*/
export async function racePeering(
origin: string,
timeoutMs: number,
ensurePeeredFn: (origin: string) => Promise<EnsurePeeredResult> = ensurePeered,
): Promise<EnsurePeeredResult | { status: 'timeout' }> {
const handshake = ensurePeeredFn(origin);
// Attach a warn-logged catch so a background arm that rejects AFTER the
// race loses does not trigger unhandledRejection. This runs regardless
// of which arm wins.
handshake.catch(err => {
console.warn('[federation] background handshake after call-relay race:', origin, err);
});
let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
const timeoutPromise = new Promise<{ status: 'timeout' }>(resolve => {
timeoutHandle = setTimeout(() => resolve({ status: 'timeout' }), timeoutMs);
});
try {
return await Promise.race([handshake, timeoutPromise]);
} finally {
if (timeoutHandle) clearTimeout(timeoutHandle);
}
}