From 2da6906be8a33967bf747addfca4851ee9394e9a Mon Sep 17 00:00:00 2001 From: Gaurav Bhola Date: Thu, 2 Apr 2026 20:14:54 -0700 Subject: [PATCH] fix(web): prevent SSE effect from re-running on every mux snapshot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- packages/web/src/hooks/useSessionEvents.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/web/src/hooks/useSessionEvents.ts b/packages/web/src/hooks/useSessionEvents.ts index 4ad3b1d0f..a90011aba 100644 --- a/packages/web/src/hooks/useSessionEvents.ts +++ b/packages/web/src/hooks/useSessionEvents.ts @@ -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; }