From 585e7d22264f3ed5c184cb1e85407aed3d522d75 Mon Sep 17 00:00:00 2001 From: Jose Selesan Date: Fri, 17 Apr 2026 17:34:04 -0300 Subject: [PATCH] feat: implement polling fallback for SSE connection failures and add event deduplication --- apps/frontend/src/features/home/home-page.tsx | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/apps/frontend/src/features/home/home-page.tsx b/apps/frontend/src/features/home/home-page.tsx index 0ff90c9..44375c4 100644 --- a/apps/frontend/src/features/home/home-page.tsx +++ b/apps/frontend/src/features/home/home-page.tsx @@ -172,7 +172,9 @@ export function HomePage() { let eventSource: EventSource | null = null; let reconnectTimeout: ReturnType | null = null; let reconnectAttempts = 0; - const maxReconnectAttempts = 5; + const maxReconnectAttempts = 3; + let lastEventId: string | null = null; + let pollInterval: ReturnType | null = null; const connect = () => { if (eventSource) { @@ -180,7 +182,8 @@ export function HomePage() { } if (reconnectAttempts >= maxReconnectAttempts) { - console.log('[SSE] Max reconnect attempts reached'); + console.log('[SSE] Max reconnect attempts reached, switching to polling'); + startPolling(); return; } @@ -191,30 +194,46 @@ export function HomePage() { eventSource.onerror = () => { if (eventSource?.readyState === EventSource.CLOSED) { reconnectAttempts++; - const delay = Math.min(1000 * 2 ** reconnectAttempts, 30000); console.log( - `[SSE] Connection closed, retry ${reconnectAttempts}/${maxReconnectAttempts} in ${delay}ms` + `[SSE] Connection closed, retry ${reconnectAttempts}/${maxReconnectAttempts}` ); reconnectTimeout = setTimeout(() => { connect(); - }, delay); + }, 2000); } }; eventSource.addEventListener('message', (event) => { if (event.data && event.data !== 'connected' && event.data !== 'ping') { - reconnectAttempts = 0; - void queryClient.invalidateQueries({ queryKey: ['admin-bookings', selectedComplex.id] }); + if (event.data !== lastEventId) { + lastEventId = event.data; + reconnectAttempts = 0; + void queryClient.invalidateQueries({ + queryKey: ['admin-bookings', selectedComplex.id], + }); + } } }); }; + const startPolling = () => { + if (pollInterval) return; + + console.log('[SSE] Starting polling fallback'); + pollInterval = setInterval(() => { + void queryClient.invalidateQueries({ queryKey: ['admin-bookings', selectedComplex.id] }); + }, 10000); + }; + connect(); return () => { if (reconnectTimeout) { clearTimeout(reconnectTimeout); } + if (pollInterval) { + clearInterval(pollInterval); + } eventSource?.close(); }; }, [selectedComplex?.id, queryClient]);