Harden chat WebSocket for mobile lifecycle (background/resume, network switch, reconnect) #23

Closed
opened 2026-07-26 04:54:29 -07:00 by westfarn · 0 comments
Owner

Risk

Blocks #20 (Android) and #21 (iOS).

Live chat runs over REACT_APP_BACKEND_WS_API_BASE_URL (wss://chatbackend.aimloperations.com/ws/chat_again/) from the WebSocket context in src/llm-fe/contexts/. On desktop the tab stays alive, so a fragile connection is rarely noticed. On mobile the OS suspends the WebView on backgrounding and tears down sockets (iOS aggressively, Android on doze/low memory), and the socket also dies when the device switches cellular to WiFi. Without reconnect logic the user returns to a dead chat with no error, and in-flight streamed responses are lost.

Work

  • Review the current WebSocket context: does it detect close/error, and does it retry at all?
  • Add reconnect with exponential backoff plus jitter, and a cap on attempts.
  • Reconnect on Capacitor App resume and on @capacitor/network connectivity change, not only on socket close.
  • Re-authenticate on reconnect (JWT may have expired while backgrounded) - coordinate with #22.
  • Decide recovery semantics for a response that was streaming when the socket dropped: resume, refetch the conversation, or mark the message failed with a retry affordance.
  • Surface connection state in the UI (reconnecting indicator, disabled send while down) instead of silently dropping messages.
  • Add a heartbeat/ping if the backend or any proxy idles connections out; check nginx / web-static proxy timeouts for the /ws/ path.
  • Test matrix: background 30s, background 10min, airplane mode on/off, cellular to WiFi, lock screen, low-power mode.

Done when

Backgrounding the app or switching networks returns to a working chat without a manual reload, and connection state is visible to the user.

## Risk Blocks #20 (Android) and #21 (iOS). Live chat runs over `REACT_APP_BACKEND_WS_API_BASE_URL` (`wss://chatbackend.aimloperations.com/ws/chat_again/`) from the WebSocket context in `src/llm-fe/contexts/`. On desktop the tab stays alive, so a fragile connection is rarely noticed. On mobile the OS suspends the WebView on backgrounding and tears down sockets (iOS aggressively, Android on doze/low memory), and the socket also dies when the device switches cellular to WiFi. Without reconnect logic the user returns to a dead chat with no error, and in-flight streamed responses are lost. ## Work - [ ] Review the current WebSocket context: does it detect close/error, and does it retry at all? - [ ] Add reconnect with exponential backoff plus jitter, and a cap on attempts. - [ ] Reconnect on Capacitor `App` `resume` and on `@capacitor/network` connectivity change, not only on socket `close`. - [ ] Re-authenticate on reconnect (JWT may have expired while backgrounded) - coordinate with #22. - [ ] Decide recovery semantics for a response that was streaming when the socket dropped: resume, refetch the conversation, or mark the message failed with a retry affordance. - [ ] Surface connection state in the UI (reconnecting indicator, disabled send while down) instead of silently dropping messages. - [ ] Add a heartbeat/ping if the backend or any proxy idles connections out; check nginx / web-static proxy timeouts for the `/ws/` path. - [ ] Test matrix: background 30s, background 10min, airplane mode on/off, cellular to WiFi, lock screen, low-power mode. ## Done when Backgrounding the app or switching networks returns to a working chat without a manual reload, and connection state is visible to the user.
westfarn added a new dependency 2026-07-26 04:55:28 -07:00
westfarn added a new dependency 2026-07-26 04:55:28 -07:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Reference: ai_ml_operations/chat_web_app#23