feat(sse): hoist EventSource to module singleton #613
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!613
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "dev/605"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Moves
EventSourceout of eachuseSSEhook into module scope so route navigation no longer tears down and re-opens the stream — eliminating the Firefox "La connexion … a été interrompue" console spam (#605).First subscriber opens the connection; last unmount schedules a 1 s grace-window close; a new subscriber within the window cancels it so back-to-back unmount/mount (route nav, StrictMode) keeps the existing
EventSourcerunning.onEvent/onReconnectcallbacks are multiplexed across all active consumers; connection state is broadcast viauseSyncExternalStore. Public API (useSSE,forceReconnect,_resetInitialConnectionToastForTest) is unchanged — no call sites need updating.Test plan
sse.test.ts(new): refcount open-on-first / close-after-last, grace-window cancel on quick remount, multiplexedonEventto two subscribers,forceReconnectkeeps the shared connection alive for other subscribers.bun x turbo run test --filter @claude-hooks/web— 579 tests pass, 50 files.bun x turbo run typecheck --filter @claude-hooks/web— clean.Closes #605
Singleton connection + refcount + grace-window are all correct.
useSyncExternalStorebroadcast, stable-ref callback wrappers, and multiplexed dispatch are clean. All 5 AC test cases covered; CI green.Nit (no block):
_resetModuleStateForTestdoes not call_storeListeners.clear()— harmless in practice because tests unmount their hooks explicitly, but worth adding for completeness.