fix: reconnect SSE immediately on OS wake-from-sleep (#1066)

* fix: reconnect SSE immediately on OS wake-from-sleep

When the desktop app resumes from OS sleep, TCP connections are dead
but timers were paused during sleep so the heartbeat watchdog doesn't
fire until ~30s after wake.

Add Electron powerMonitor.resume → renderer notification → event-pipeline
immediate abort, cutting reconnection delay from ~30s to ~0ms.

Changes:
- electron/main.mjs: import powerMonitor, emit openchamber:system-resume
  to all renderer windows on OS resume
- ui/sync/event-pipeline.ts: listen for openchamber:system-resume, set
  attemptAbortReason and abort the active SSE/WS attempt to trigger
  immediate reconnection with retryDelayMs=0 and lastEventId preservation

* fix: reconnect SSE immediately on OS wake-from-sleep

When the desktop app resumes from OS sleep, TCP connections are dead
but timers were paused during sleep so the heartbeat watchdog doesn't
fire until ~30s after wake.

Add Electron powerMonitor.resume → renderer notification → event-pipeline
immediate abort, cutting reconnection delay from ~30s to ~0ms.

Changes:
- electron/main.mjs: import powerMonitor, emit openchamber:system-resume
  to all renderer windows on OS resume
- ui/sync/event-pipeline.ts: listen for openchamber:system-resume via
  globalThis.window, set attemptAbortReason and abort the active SSE/WS
  attempt to trigger immediate reconnection with retryDelayMs=0 and
  lastEventId preservation
- Test: event-pipeline-resume.test.js verifies abort → reconnect flow
This commit is contained in:
jwcrystal
2026-04-29 12:19:31 +03:00
committed by GitHub
parent 21253d7fc2
commit 9424cff02c
3 changed files with 138 additions and 1 deletions
+7 -1
View File
@@ -1,4 +1,4 @@
import { app, BrowserWindow, dialog, ipcMain, Menu, nativeTheme, Notification, session, shell } from 'electron';
import { app, BrowserWindow, dialog, ipcMain, Menu, nativeTheme, Notification, powerMonitor, session, shell } from 'electron';
import contextMenu from 'electron-context-menu';
import log from 'electron-log/main.js';
import dgram from 'node:dgram';
@@ -2366,6 +2366,12 @@ app.whenReady().then(async () => {
const { initialUrl, localOrigin, bootOutcome } = await resolveInitialUrl();
await activateMainWindow(initialUrl, localOrigin, bootOutcome);
startQuitRiskPoller();
// Notify renderer on OS wake-from-sleep so the SSE event pipeline can
// reconnect immediately instead of waiting for the heartbeat watchdog.
powerMonitor.on('resume', () => {
emitToAllWindows('openchamber:system-resume', { timestamp: Date.now() });
});
}).catch((error) => {
log.error('[electron] startup failed:', error);
app.exit(1);