fix(web): recover silently-dead SSE connections quickly, stop banner noise (#1562)

A suspended mobile tab can lose its SSE connection without the browser
ever noticing (no FIN/RST arrives). On resume the client used to wait
for the 90s heartbeat watchdog or lean on the native EventSource retry,
which can hang on a dead pooled socket - leaving a persistent
"Reconnecting... (stream error)" banner while the UI keeps working.

- useSSE: on visibility resume, distrust the connection after one missed
  heartbeat interval (45s) instead of 90s
- useSSE: abandon connection attempts that don't open within 10s (hung
  on a dead pooled socket after resume) instead of waiting for the
  watchdog; force bypasses the one-shot reconnect guard for the new
  attempt cycle
- useSSE: first reconnect attempt is immediate; exponential backoff
  starts from the second attempt
- ReconnectingBanner: localize connect-timeout and transport-error
  reasons (transport-error is already emitted by current code but fell
  through unlabeled)

Fixes #1559. Reimplements the reconnect half of #989 (closed unmerged)
on top of the current scheduler (hidden-tab deferral, slow backoff,
replay cursor).
This commit is contained in:
SSU-WEI HUANG
2026-08-15 11:16:19 +08:00
committed by GitHub
parent 235d6dd6fd
commit a794be0811
5 changed files with 202 additions and 8 deletions
+2
View File
@@ -699,6 +699,8 @@ export default {
'reconnecting.reason.closed': 'stream closed',
'reconnecting.reason.heartbeatTimeout': 'heartbeat timeout',
'reconnecting.reason.visibilityRecovery': 'resuming after background',
'reconnecting.reason.connectTimeout': 'connect timeout',
'reconnecting.reason.transportError': 'stream error',
'pwa.update.title': 'New version available',
'pwa.update.body': 'Reload to get the latest HAPI',
'pwa.update.reload': 'Reload',
+2
View File
@@ -698,6 +698,8 @@ export default {
'reconnecting.reason.closed': '流连接已关闭',
'reconnecting.reason.heartbeatTimeout': '心跳超时',
'reconnecting.reason.visibilityRecovery': '后台恢复中',
'reconnecting.reason.connectTimeout': '连接超时',
'reconnecting.reason.transportError': '流连接错误',
'pwa.update.title': '新版本可用',
'pwa.update.body': '重新加载以获取最新版 HAPI',
'pwa.update.reload': '重新加载',