Skip to content

fix(web): suppress false offline errors and refetch data on tab resume - #787

Merged
evilguy4000 merged 1 commit into
DRYTRIX:developfrom
Giorgio-Germani:fix/tab-resume-refetch
Oct 16, 2026
Merged

evilguy4000 merged 1 commit into
DRYTRIX:developfrom
Giorgio-Germani:fix/tab-resume-refetch

Conversation

@Giorgio-Germani

Copy link
Copy Markdown

Problem

After a browser tab sat in the background for a while (e.g. during lunch), returning to it showed "Unable to connect to the server" even though the server was healthy. Console showed a burst of ERR_CONNECTION_CLOSED and proxy 503/504s on /socket.io/, /api/health, /timer/status, /api/notifications.

Cause: while backgrounded, the browser suspends JS timers and the proxy eventually closes the idle keep-alive/long-poll connections. On resume, the tab fires a burst of requests; several land on dead keep-alive sockets (network errors) and the rest hit the reconnect burst. The one-shot /api/health probe on visibilitychange failed during that window, so the client declared the server offline and showed the offline banner — then recovered on its own seconds later.

Fix (frontend only)

error-handling-enhanced.js:

  • 8s resume grace window: transient failures (network errors, 502/503/504) right after resume no longer pop connectivity toasts — callers still receive the error responses, only the alarming UI is suppressed while the burst settles.
  • Backoff probes: the single /api/health probe on resume is replaced by up to 3 backoff probes (0s/2s/5s) before declaring the server offline; success at any point dismisses existing connectivity errors (existing behavior preserved).
  • tt:tab-resumed event: single debounced (1.5s) document event on tab resume.

floating-timer-bar.js:

  • refetches timer status on tt:tab-resumed
  • retries a failed status fetch exactly once after 1.5s (covers both thrown network errors and synthetic 503 responses produced by the fetch interceptor)

smart-notifications.js: polls /api/notifications on tt:tab-resumed.

Testing

  • node --check passes on all touched files
  • tests/test_reconnect_on_resume.py: the updated guard for the resume logic passes; the 3 other failures in that file (service worker / chat widget / retry-button assertions from Error Service temporarily unavailable. Please try again in a few moments. #746) fail identically on develop at baseline and are untouched by this PR
  • Verified deployed on a production instance: after backgrounding a tab for 2h, return no longer shows the offline banner; timer and notification data refetch automatically

Related: #702, #703, #746

After a tab sat in the background for a long time, returning to it fired a
burst of requests on stale keep-alive connections (ERR_CONNECTION_CLOSED /
503 from the proxy), and the one-shot health check declared the server
offline even though it was healthy.

- Add an 8s resume grace window that suppresses connectivity toasts while
  the reconnect burst settles (callers still receive the error responses)
- Replace the single /api/health probe on visibilitychange with up to 3
  backoff probes (0s/2s/5s) before showing the offline banner
- Dispatch a debounced tt:tab-resumed event; floating timer bar and smart
  notifications refetch authoritative data on it
- Floating timer bar retries a failed status fetch once (network errors
  surface as synthetic 503 responses via the fetch interceptor)
@evilguy4000
evilguy4000 merged commit 6feee4e into DRYTRIX:develop Oct 16, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants