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
@@ -1,5 +1,6 @@
import { describe, it, expect } from 'vitest';
import { describe, it, expect, vi } from 'vitest';
import type { EnsurePeeredResult } from './federationPeering.js';
import { racePeering } from './federationPeering.js';
describe('EnsurePeeredResult type', () => {
it('active result has peerId', () => {
@@ -43,3 +44,49 @@ describe('EnsurePeeredResult type', () => {
}
});
});
describe('racePeering', () => {
it('returns the ensurePeered result when it resolves before the timeout', async () => {
const stub = vi.fn(async (): Promise<EnsurePeeredResult> => ({
status: 'active',
peerId: 'peer-1',
}));
const result = await racePeering('https://example.com', 1_000, stub);
expect(result).toEqual({ status: 'active', peerId: 'peer-1' });
expect(stub).toHaveBeenCalledWith('https://example.com');
});
it('returns timeout when ensurePeered takes longer than the deadline', async () => {
const stub = vi.fn((): Promise<EnsurePeeredResult> => new Promise(() => {
// Never resolves — simulates a slow handshake.
}));
const result = await racePeering('https://example.com', 50, stub);
expect(result).toEqual({ status: 'timeout' });
});
it('returns rejected result verbatim when ensurePeered resolves with rejection', async () => {
const stub = vi.fn(async (): Promise<EnsurePeeredResult> => ({
status: 'rejected',
error: 'peer denied',
}));
const result = await racePeering('https://example.com', 1_000, stub);
expect(result).toEqual({ status: 'rejected', error: 'peer denied' });
});
it('attaches a warn-logged catch to the background promise so race-losing rejections do not emit unhandledRejection', async () => {
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
const stub = vi.fn(() => new Promise<EnsurePeeredResult>((_, reject) => {
setTimeout(() => reject(new Error('late failure')), 30);
}));
const result = await racePeering('https://example.com', 10, stub);
expect(result).toEqual({ status: 'timeout' });
// Give the background promise time to reject.
await new Promise(r => setTimeout(r, 50));
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining('background handshake'),
'https://example.com',
expect.any(Error),
);
warnSpy.mockRestore();
});
});