fix(web): prevent SSE effect from re-running on every mux snapshot

The SSE effect had muxSessions (array reference) in its deps, causing
it to re-run on every snapshot and fire cleanup that cleared the
debounce timer the mux effect intentionally preserved.

- Derive muxActive = muxSessions !== undefined and use that in SSE
  effect deps — the effect now only re-runs when mux transitions
  between present/absent, not on every new array reference
- Add reschedule in scheduleRefresh .finally() abort path: when a
  fetch is aborted mid-flight (by a new snapshot) and there is still
  a pending membership key, reschedule so the refresh isn't silently
  dropped

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Gaurav Bhola 2026-04-02 20:14:54 -07:00
parent c418f852e2
commit 2da6906be8
1 changed files with 11 additions and 2 deletions

View File

@ -136,6 +136,11 @@ export function useSessionEvents(
});
}, [initialSessions, initialGlobalPause]);
// Stable boolean — only changes when mux transitions between present/absent,
// not on every new snapshot array reference. Used in the SSE effect deps so
// SSE setup/teardown runs only on that transition, not every mux update.
const muxActive = muxSessions !== undefined;
// Define scheduleRefresh with useCallback so both effects can use it
const scheduleRefresh = useCallback(() => {
if (refreshingRef.current || refreshTimerRef.current) return;
@ -174,6 +179,10 @@ export function useSessionEvents(
}
if (refreshController.signal.aborted) {
refreshingRef.current = false;
// If there's still a pending membership change, reschedule so it isn't lost
if (pendingMembershipKeyRef.current !== null) {
scheduleRefresh();
}
return;
}
@ -221,7 +230,7 @@ export function useSessionEvents(
useEffect(() => {
// Skip SSE if mux sessions are available
if (muxSessions) {
if (muxActive) {
dispatch({ type: "setConnection", status: "connected" });
return () => {
// Clear any pending refresh timer so it doesn't fire after unmount
@ -313,7 +322,7 @@ export function useSessionEvents(
clearDisconnectedTimer();
es.close();
};
}, [project, muxSessions, scheduleRefresh]);
}, [project, muxActive, scheduleRefresh]);
return state;
}