diff --git a/relay/test/harness.ts b/relay/test/harness.ts index 97c7258..1ea76da 100644 --- a/relay/test/harness.ts +++ b/relay/test/harness.ts @@ -107,6 +107,23 @@ export async function idleTimeout(hub: DurableObjectStub, ms: number): Promise { + await runInDurableObject(hub, (instance) => { + const withEnv = instance as unknown as { env: Record } + withEnv.env = { ...withEnv.env, PAIR_TIMEOUT_MS: ms } + }) +} + export function sleep(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)) } diff --git a/relay/test/pair.test.ts b/relay/test/pair.test.ts index 2abfe6c..6b64a52 100644 --- a/relay/test/pair.test.ts +++ b/relay/test/pair.test.ts @@ -10,10 +10,11 @@ import { freshHub, hubPath, MACHINE, + pairTimeout, type Leg, } from './harness' -/** Mirrors the PAIR_TIMEOUT_MS binding in vitest.config.ts. */ +/** The deadline the one timeout test binds for itself via pairTimeout(). */ const PAIR_TIMEOUT_MS = 250 /** The body cap, matching the daemon's own maxPairBytes (internal/daemon/pairing.go). */ @@ -292,6 +293,7 @@ describe('the cap on concurrent pairing attempts', () => { describe('a daemon that does not answer', () => { it('times out with 504 daemon did not answer', async () => { const hub = freshHub() + await pairTimeout(hub, PAIR_TIMEOUT_MS) const daemon = await dial(hub, `/daemon/${MACHINE}`) const started = Date.now() const res = await post(hub, '{"token":"t"}') diff --git a/relay/vitest.config.ts b/relay/vitest.config.ts index 946d8af..0fa5f68 100644 --- a/relay/vitest.config.ts +++ b/relay/vitest.config.ts @@ -23,9 +23,13 @@ import { defineConfig } from 'vitest/config' * before they dial. A test that says nothing about the deadline is no longer * making a silent bet on how fast the runner is. * - * The pairing deadline stays short and stays the looser of the two, because the - * tests that must *not* hit it run a whole HTTP request through a WebSocket - * round trip first. + * The pairing deadline is bound long by the same rule, and it earned its + * place the same way the handshake deadline did. It used to stay short — + * 250 ms, on the reasoning that the tests that must not hit it run a whole + * HTTP request through a WebSocket round trip first — and a loaded CI + * runner eventually stalled past that: four pair tests 504ed in one run, + * none reproducible locally. The one test about the timeout binds its own + * short deadline with `pairTimeout()` before it dials. * * CLIENT_IDLE_TIMEOUT_MS is bound the same way and for the same reason: a test * client sends when its test needs it to and is otherwise silent — it sends no @@ -41,7 +45,7 @@ export default defineConfig({ bindings: { HANDSHAKE_TIMEOUT_MS: 600_000, CLIENT_IDLE_TIMEOUT_MS: 600_000, - PAIR_TIMEOUT_MS: 250, + PAIR_TIMEOUT_MS: 600_000, // The directory's entry cap, bound small for the same reason the // deadlines above are bound at all: the only way to test a cap is to // reach it, and reaching the production 512 is 512 sequential round