From 43f804c7a8ab99601f6b8bdd7610b6f8afb5b76d Mon Sep 17 00:00:00 2001 From: Mo Tarbin Date: Tue, 30 Jun 2026 01:21:17 -0400 Subject: [PATCH] Fix: Export polling constants and synchronize retry intervals in SyncStatusIndicator --- src/hooks/useSyncOnReconnect.js | 4 +- src/views/components/SyncStatusIndicator.jsx | 49 ++++++++++++++++---- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/hooks/useSyncOnReconnect.js b/src/hooks/useSyncOnReconnect.js index f60151c..0c3220e 100644 --- a/src/hooks/useSyncOnReconnect.js +++ b/src/hooks/useSyncOnReconnect.js @@ -8,9 +8,9 @@ import { isOfflineFeatureEnabled } from '../utils/OfflineFeatureToggle' import { syncEngine } from '../utils/SyncEngine' import { networkManager } from './NetworkManager' -const PENDING_POLL_MS = 30_000 // retry pending commands every 30s +export const PENDING_POLL_MS = 30_000 // retry pending commands every 30s +export const SERVER_PROBE_MS = 15_000 // probe server when marked unreachable but device has network const CACHE_REFRESH_MS = 5 * 60_000 // refresh IDB cache every 5 min while online -const SERVER_PROBE_MS = 15_000 // probe server when marked unreachable but device has network export function useSyncOnReconnect() { const queryClient = useQueryClient() diff --git a/src/views/components/SyncStatusIndicator.jsx b/src/views/components/SyncStatusIndicator.jsx index 7900b7d..0f0aee5 100644 --- a/src/views/components/SyncStatusIndicator.jsx +++ b/src/views/components/SyncStatusIndicator.jsx @@ -23,8 +23,12 @@ import { Typography, } from '@mui/joy' import { useQueryClient } from '@tanstack/react-query' -import { useEffect, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { networkManager } from '../../hooks/NetworkManager' +import { + PENDING_POLL_MS, + SERVER_PROBE_MS, +} from '../../hooks/useSyncOnReconnect' import { commandQueue } from '../../utils/CommandQueue' import { isOfflineFeatureEnabled, @@ -57,8 +61,6 @@ const formatCommandLabel = commandType => { ) } -const RETRY_INTERVAL = 30 - function SyncStatusIndicator() { const queryClient = useQueryClient() const [pendingCommands, setPendingCommands] = useState([]) @@ -71,7 +73,17 @@ function SyncStatusIndicator() { const [isOnline, setIsOnline] = useState(networkManager.isOnline) const [offlineSince, setOfflineSince] = useState(networkManager.offlineSince) const [offlineReason, setOfflineReason] = useState(networkManager.offlineReason) - const [retryIn, setRetryIn] = useState(RETRY_INTERVAL) + + // Mirror the actual intervals used by useSyncOnReconnect so the countdown is accurate + const retryInterval = useMemo( + () => + !isOnline && offlineReason === 'server' + ? SERVER_PROBE_MS / 1000 + : PENDING_POLL_MS / 1000, + [isOnline, offlineReason], + ) + + const [retryIn, setRetryIn] = useState(retryInterval) const [offlineFeatureEnabled, setOfflineFeatureEnabled] = useState( isOfflineFeatureEnabled(), ) @@ -90,9 +102,9 @@ function SyncStatusIndicator() { useEffect(() => { if (!syncState.syncing) { - setRetryIn(RETRY_INTERVAL) + setRetryIn(retryInterval) } - }, [syncState.syncing, syncState.lastSync]) + }, [syncState.syncing, syncState.lastSync, retryInterval]) useEffect(() => { networkManager.registerNetworkListener(online => { @@ -108,10 +120,31 @@ function SyncStatusIndicator() { if (isOnline && pendingCommands.length === 0) return if (!isOnline && offlineReason === 'device') return const interval = setInterval(() => { - setRetryIn(prev => (prev <= 1 ? RETRY_INTERVAL : prev - 1)) + setRetryIn(prev => { + if (prev <= 1) { + console.debug('[SyncStatusIndicator] Retry timer fired', { + isOnline, + offlineReason, + syncing: syncState.syncing, + lastSync: syncState.lastSync, + error: syncState.error, + pendingCommands: pendingCommands.length, + }) + return retryInterval + } + return prev - 1 + }) }, 1000) return () => clearInterval(interval) - }, [isOnline, offlineReason, syncState.syncing, syncState.lastSync, pendingCommands.length]) + }, [ + isOnline, + offlineReason, + syncState.syncing, + syncState.lastSync, + syncState.error, + pendingCommands.length, + retryInterval, + ]) useEffect(() => { const update = async () => {