Files
buzz/desktop/src/shared/api/relayReconnectWaiters.ts
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

22 lines
480 B
TypeScript

export class RelayReconnectWaiters {
private waiters = new Set<{
resolve: () => void;
reject: (error: Error) => void;
}>();
wait(): Promise<void> {
return new Promise<void>((resolve, reject) => {
this.waiters.add({ resolve, reject });
});
}
settle(error?: Error) {
const waiters = [...this.waiters];
this.waiters.clear();
for (const waiter of waiters) {
if (error) waiter.reject(error);
else waiter.resolve();
}
}
}