From 20f5c1a3610ccd4d5f9ad1d79e76d7be5dd82fca Mon Sep 17 00:00:00 2001 From: kerboul Date: Tue, 31 Mar 2026 15:17:50 +0200 Subject: [PATCH] feat: Valhalla status poll loop with IPC/fetch dual-mode Co-Authored-By: Claude Sonnet 4.6 --- src/renderer/src/App.tsx | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index ab16641..33382d8 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -15,12 +15,28 @@ function App(): React.JSX.Element { const autoRecalculate = useAppStore((s) => s.autoRecalculate) const autoTimerRef = useRef | null>(null) - // Probe Valhalla status at startup + // Get Valhalla status — IPC in Electron, fetch poll in web useEffect(() => { + if (window.api) { + window.api.getValhallaStatus().then((s) => setValhallaStatus(s)) + window.api.onValhallaStatus((s) => setValhallaStatus(s)) + return + } const base = (import.meta.env.VITE_VALHALLA_URL as string | undefined) ?? 'http://127.0.0.1:8002' - fetch(`${base}/status`, { signal: AbortSignal.timeout(3000) }) - .then((r) => setValhallaStatus(r.ok ? 'ready' : 'error')) - .catch(() => setValhallaStatus('error')) + const deadline = Date.now() + 180000 + let cancelled = false + const poll = async (): Promise => { + while (!cancelled && Date.now() < deadline) { + try { + const r = await fetch(`${base}/status`, { signal: AbortSignal.timeout(2000) }) + if (r.ok) { setValhallaStatus('ready'); return } + } catch { /* not ready yet */ } + await new Promise((r) => setTimeout(r, 1000)) + } + if (!cancelled) setValhallaStatus('error') + } + poll() + return () => { cancelled = true } }, []) // eslint-disable-line react-hooks/exhaustive-deps // Auto-calculate once Valhalla is ready