fix(ws): delay reconnect banner so page nav does not flash it (LC-318) #343

Merged
nrupard merged 2 commits from fix/lc-318-reconnect-banner-grace into main 2026-06-17 21:16:56 +02:00
Owner

What

Delay the WebSocket connection-status banner so a normal page navigation no longer flashes "Connection lost. Reconnecting...".

Why

The banner state machine in layout.html painted the reconnecting banner the instant htmx:wsClose fired. A boosted page navigation swaps the ws-connect element, which briefly closes and reopens the socket, so the banner flashed for about a second on every page move (LC-318), including bouncing between the same two pages.

Fix

enterReconnecting now schedules the banner paint behind a GRACE_MS (3s) timer instead of painting immediately. If the socket reopens within the window (the navigation case), enterConnected clears the pending timer silently: no banner, no green "Connected" flash, and no soft-refresh (the freshly navigated page already has current content). Only an outage that outlasts the grace paints "Reconnecting" and starts the existing 5-minute escalation to "Still trying to reconnect"; a real reconnect after the banner was shown still flashes "Connected" and soft-refreshes #main to recover missed content.

Test

just test and just test-saas green; cargo check clean (Askama compiles the template). routes_reconnect.rs still passes (banner element + baseline data-state="hidden" + #main wrapper unchanged). Manual: navigate between pages repeatedly (no flash); kill the server (banner appears after ~3s, escalates, then flashes "Connected" + refreshes on recovery).

#LC-318

## What Delay the WebSocket connection-status banner so a normal page navigation no longer flashes "Connection lost. Reconnecting...". ## Why The banner state machine in `layout.html` painted the reconnecting banner the instant `htmx:wsClose` fired. A boosted page navigation swaps the `ws-connect` element, which briefly closes and reopens the socket, so the banner flashed for about a second on every page move (LC-318), including bouncing between the same two pages. ## Fix `enterReconnecting` now schedules the banner paint behind a `GRACE_MS` (3s) timer instead of painting immediately. If the socket reopens within the window (the navigation case), `enterConnected` clears the pending timer silently: no banner, no green "Connected" flash, and no soft-refresh (the freshly navigated page already has current content). Only an outage that outlasts the grace paints "Reconnecting" and starts the existing 5-minute escalation to "Still trying to reconnect"; a real reconnect after the banner was shown still flashes "Connected" and soft-refreshes `#main` to recover missed content. ## Test `just test` and `just test-saas` green; `cargo check` clean (Askama compiles the template). `routes_reconnect.rs` still passes (banner element + baseline `data-state="hidden"` + `#main` wrapper unchanged). Manual: navigate between pages repeatedly (no flash); kill the server (banner appears after ~3s, escalates, then flashes "Connected" + refreshes on recovery). #LC-318
fix(ws): delay reconnect banner so page nav does not flash it
All checks were successful
check-secrets / Nosey parker (push) Successful in 3s
check-secrets / TruffleHog (push) Successful in 7s
check-secrets / Kingfisher (push) Successful in 9s
check-secrets / Nosey parker (pull_request) Successful in 3s
check-secrets / TruffleHog (pull_request) Successful in 9s
check-secrets / Kingfisher (pull_request) Successful in 9s
Check / clippy + fmt + tests (pull_request) Successful in 4m44s
7cfae7d36a
The connection-status banner state machine painted "Connection lost. Reconnecting..." the instant `htmx:wsClose` fired. A normal page navigation (hx-boost swaps the ws-connect element) briefly closes and reopens the socket, so the banner flashed for about a second on every page move, including going back and forth between the same two pages.

Defer the banner by a GRACE_MS (3s) window: enterReconnecting now schedules the paint instead of painting immediately, and enterConnected cancels a still-pending grace timer silently. Only an outage that outlasts the grace paints "Reconnecting" and starts the 5min escalation clock. The green "Connected" flash and the soft-refresh now fire only when the banner was actually shown (real outage), not on a navigation whose new page is already fresh.

#LC-318

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix(ws): keep missed-content recovery on short real outages
All checks were successful
check-secrets / Nosey parker (pull_request) Successful in 4s
check-secrets / Nosey parker (push) Successful in 7s
check-secrets / TruffleHog (pull_request) Successful in 8s
check-secrets / Kingfisher (pull_request) Successful in 11s
check-secrets / TruffleHog (push) Successful in 11s
check-secrets / Kingfisher (push) Successful in 12s
Create release / Create release from merged PR (pull_request) Has been skipped
Check / clippy + fmt + tests (pull_request) Successful in 2m57s
128ff46cef
Code-review follow-up to the grace-delay change. Gating the reconnect soft-refresh on whether the banner was shown meant a genuine WS outage shorter than the 3s grace (e.g. a 2s network drop) reconnected without refreshing #main, so events the server broadcast during the gap were never rendered (the server does not replay on reconnect; the soft-refresh is the only recovery path).

Track an abnormalClose flag set from the wsClose code: genuine outages (1006 abnormal, 1011 server error, 1012/1013 restart, our own 4000 half-open kill) flag it; a page navigation does not (htmx-ext-ws closes with no code, reported as 1005) nor does a clean 1000/1001 going-away. enterConnected runs the soft-refresh when the banner was shown OR abnormalClose was flagged, so short real outages recover while navigations still neither flash nor double-fetch. Also drops the now-dead wasReconnecting parameter.

#LC-318

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nrupard deleted branch fix/lc-318-reconnect-banner-grace 2026-06-17 21:16:56 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!343
No description provided.