fix(tlon): clear SSE connect timeout after failed openStream#104585
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 14, 2026, 9:25 PM ET / July 15, 2026, 01:25 UTC. Summary PR surface: Source -1, Tests +159. Total +158 across 3 files. Reproducibility: yes. at the source level: current Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the Do we have a high-confidence way to reproduce the issue? Yes at the source level: current Is this the best way to solve the issue? Yes. Moving the existing timer cleanup into AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 3c0654c00271. Label changesLabel justifications:
Evidence reviewedPR surface: Source -1, Tests +159. Total +158 across 3 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (28 earlier review cycles; latest 8 shown)
|
1c618ac to
a6f2fb7
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
a6f2fb7 to
f79d2ee
Compare
f79d2ee to
8bdd6d4
Compare
c597d5c to
2e5a551
Compare
3ee883a to
5cf6f37
Compare
5cf6f37 to
2f3769f
Compare
|
Land-ready proof for exact head
Known gap: no live reconnect storm was induced against a real Tlon ship. The exercised network path is the production SSRF-guarded transport with real sockets and timers; no fetch mock or fake timer is used in the integration proof. |
|
Merged via squash.
|
…w#104585) * fix(tlon): clear SSE connect timeout after failed openStream * refactor(tlon): scope SSE connect timeout --------- Co-authored-by: Peter Steinberger <[email protected]>
What Problem This Solves
Fixes an issue where Tlon Urbit SSE
openStreamarmed a 60s connectsetTimeoutand only cleared it after a successfulurbitFetch. When the connect fetch rejected (DNS/SSRF/network) or returned non-OK, the timer stayed armed until it fired, and reconnect storms could stack dangling timers in the Gateway process.Why This Change Was Made
Wrap the connect fetch in
try/finallyand alwaysclearTimeout, matching the zalouser probe timeout cleanup pattern, so failed connects release the timer immediately without changing the connect deadline or stream lifecycle.User Impact
Flaky Urbit hosts no longer leave dangling connect timers in long-running Tlon monitors during reconnect failures.
Evidence
Unit regression (mocked fetch + fake timers)
Production-path connect-timeout storm proof
The storm case runs production
openStream→urbitFetch→fetchWithSsrFGuardagainst a real loopbacknode:httpserver that returns503five times; real timers; each armedsetTimeout(..., 60000)is cleared. The reject case uses a closed loopback port (127.0.0.1:9) so the production transport fails before headers.Real behavior proof
UrbitSSEClient.openStream→ productionurbitFetch/fetchWithSsrFGuard→ reject or non-OK →finally { clearTimeout(timeoutId) }.node:http+ closed-port TCP failure; production SSRF-guarded transport (nourbitFetchmock, no fake timers).try/finally { clearTimeout }pattern asextensions/zalouser/src/probe.ts; no new config/API.node scripts/run-vitest.mjswith real HTTP listeners and real timers.node scripts/run-vitest.mjs extensions/tlon/src/urbit/sse-client.open-stream-timeout.proof.test.ts extensions/tlon/src/urbit/sse-client.test.ts --reporter=verboseclearTimeout(handle); a real transport reject also clears its single connect timer.Risk / Compatibility
Low. Successful connects still clear the timer after headers; only failed connects gain the missing cleanup.