Files
buzz/desktop/src/shared/api/relayReconnectPolicy.test.mjs
Wes cca8839034 Make relay reconnect backoff authoritative (#3774)
## Summary

- make the relay reconnect coordinator authoritative during outages so
query, publish, and subscription traffic waits for the scheduled attempt
instead of cancelling backoff
- release waiting operations after the coordinated AUTH +
live-subscription replay attempt, while preserving one explicit manual
reconnect fast path
- suppress duplicate notification side effects when reconnect replay
overlaps previously delivered events

## Root cause

`resetConnection()` scheduled exponential backoff, but
`ensureConnected()` cleared any pending reconnect timer. Operation-level
retry paths immediately called `ensureConnected()`, so ordinary app
traffic could repeatedly bypass the reconnect policy during an outage.
The resulting churn also replayed overlapping live events into
notification side effects without a shared event-ID guard.

## Validation

- `pnpm --dir desktop typecheck`
- `pnpm --dir desktop test` — 3,823 passed
- pre-push: `desktop-check`, `desktop-test`, and `branch-skew` passed
- file-size, px-text, and pubkey-truncation ratchets passed

---------

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
2026-07-30 11:25:08 -07:00

120 lines
3.3 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import {
isServiceRestartClose,
isWebSocketClose,
shouldRefuseConnect,
shouldScheduleReconnect,
shouldWaitForScheduledReconnect,
} from "./relayReconnectPolicy.ts";
// The "happy" baseline that *should* schedule a reconnect: not terminal,
// no pending timer, no live socket, and at least something keeping the
// session alive (a live subscription, in this case).
const baseline = Object.freeze({
terminal: false,
hasPendingReconnect: false,
hasLiveSocket: false,
keepAliveRequested: false,
hasLiveSubscriptions: true,
});
test("baseline scenario schedules a reconnect", () => {
assert.equal(shouldScheduleReconnect({ ...baseline }), true);
});
test("terminal session refuses to schedule (Max's auth-rejection scenario)", () => {
assert.equal(shouldScheduleReconnect({ ...baseline, terminal: true }), false);
});
test("terminal beats every other reason to reconnect", () => {
// Even with every "yes please reconnect" predicate flipped on, terminal
// wins. This is the critical guarantee against the reconnect timer's
// catch handler resurrecting a dead session.
assert.equal(
shouldScheduleReconnect({
terminal: true,
hasPendingReconnect: false,
hasLiveSocket: false,
keepAliveRequested: true,
hasLiveSubscriptions: true,
}),
false,
);
});
test("pending reconnect timer suppresses scheduling another", () => {
assert.equal(
shouldScheduleReconnect({ ...baseline, hasPendingReconnect: true }),
false,
);
});
test("live socket suppresses scheduling", () => {
assert.equal(
shouldScheduleReconnect({ ...baseline, hasLiveSocket: true }),
false,
);
});
test("no live subs and no keep-alive → don't keep an idle socket up", () => {
assert.equal(
shouldScheduleReconnect({
...baseline,
hasLiveSubscriptions: false,
keepAliveRequested: false,
}),
false,
);
});
test("keep-alive alone is enough to schedule", () => {
assert.equal(
shouldScheduleReconnect({
...baseline,
hasLiveSubscriptions: false,
keepAliveRequested: true,
}),
true,
);
});
test("ordinary operations wait for a scheduled reconnect instead of bypassing backoff", () => {
assert.equal(
shouldWaitForScheduledReconnect({ hasPendingReconnect: true }),
true,
);
assert.equal(
shouldWaitForScheduledReconnect({ hasPendingReconnect: false }),
false,
);
});
test("shouldRefuseConnect mirrors terminal", () => {
assert.equal(shouldRefuseConnect({ terminal: false }), false);
assert.equal(shouldRefuseConnect({ terminal: true }), true);
});
test("only a close frame with code 1012 is a service restart", () => {
assert.equal(isWebSocketClose({ type: "Close" }), true);
assert.equal(isWebSocketClose({ type: "Error" }), false);
assert.equal(
isServiceRestartClose({
type: "Close",
data: { code: 1012, reason: "relay restarting" },
}),
true,
);
assert.equal(
isServiceRestartClose({ type: "Close", data: { code: 1000 } }),
false,
);
assert.equal(isServiceRestartClose({ type: "Close" }), false);
assert.equal(
isServiceRestartClose({ type: "Error", data: { code: 1012 } }),
false,
);
assert.equal(isServiceRestartClose(null), false);
});