diff --git a/AppImage/components/health-status-modal.tsx b/AppImage/components/health-status-modal.tsx index d4b9a64a..d189d3e9 100644 --- a/AppImage/components/health-status-modal.tsx +++ b/AppImage/components/health-status-modal.tsx @@ -151,9 +151,21 @@ export function HealthStatusModal({ open, onOpenChange, getApiUrl }: HealthStatu } }, [getApiUrl]) + // Tick counter to force re-render every 30s so "X minutes ago" stays current + const [, setTick] = useState(0) + + useEffect(() => { + if (!open) return + const tickInterval = setInterval(() => setTick(t => t + 1), 30000) + return () => clearInterval(tickInterval) + }, [open]) + useEffect(() => { if (open) { fetchHealthDetails() + // Auto-refresh every 5 minutes while modal is open + const refreshInterval = setInterval(fetchHealthDetails, 300000) + return () => clearInterval(refreshInterval) } }, [open]) diff --git a/AppImage/scripts/flask_health_routes.py b/AppImage/scripts/flask_health_routes.py index 14c5df26..5113daf2 100644 --- a/AppImage/scripts/flask_health_routes.py +++ b/AppImage/scripts/flask_health_routes.py @@ -149,10 +149,23 @@ def get_dismissed_errors(): def get_full_health(): """ Get complete health data in a single request: detailed status + active errors + dismissed. - Reduces frontend round-trips. + Uses background-cached results if fresh (< 6 min) for instant response, + otherwise runs a fresh check. """ + import time as _time try: - details = health_monitor.get_detailed_status() + # Try to use the background-cached detailed result for instant response + bg_key = '_bg_detailed' + bg_last = health_monitor.last_check_times.get(bg_key, 0) + bg_age = _time.time() - bg_last + + if bg_age < 360 and bg_key in health_monitor.cached_results: + # Use cached result (at most ~5 min old) + details = health_monitor.cached_results[bg_key] + else: + # No fresh cache, run live (first load or cache expired) + details = health_monitor.get_detailed_status() + active_errors = health_persistence.get_active_errors() dismissed = health_persistence.get_dismissed_errors() custom_suppressions = health_persistence.get_custom_suppressions() diff --git a/AppImage/scripts/flask_server.py b/AppImage/scripts/flask_server.py index 85c58b4a..23103b1e 100644 --- a/AppImage/scripts/flask_server.py +++ b/AppImage/scripts/flask_server.py @@ -590,7 +590,10 @@ def _health_collector_loop(): 'status': overall, 'summary': summary } + # Cache the full detailed result so the modal can return it instantly + health_monitor.cached_results['_bg_detailed'] = result health_monitor.last_check_times['_bg_overall'] = time.time() + health_monitor.last_check_times['_bg_detailed'] = time.time() except Exception as e: print(f"[ProxMenux] Health collector error: {e}")