From 271ecd924b16f43b25314ca31c9999908d3b0172 Mon Sep 17 00:00:00 2001 From: James Pine Date: Thu, 23 Apr 2026 21:20:50 -0700 Subject: [PATCH] perf(captures): stop polling readiness once both models are green MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit useQuery was firing GET /capture/readiness every 5s forever, and also on every window focus. Once stt.ready and llm.ready are both true the answer can only change when the user swaps a model in settings, and useSettings already invalidates the query on that path — the polling was pure noise. Gate both refetchInterval and refetchOnWindowFocus on "not fully ready" so we fall silent once the checklist is green. --- app/src/lib/hooks/useDictationReadiness.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/src/lib/hooks/useDictationReadiness.ts b/app/src/lib/hooks/useDictationReadiness.ts index 8f08df76..141ed82b 100644 --- a/app/src/lib/hooks/useDictationReadiness.ts +++ b/app/src/lib/hooks/useDictationReadiness.ts @@ -61,8 +61,18 @@ export function useDictationReadiness(): DictationReadiness { const { data, isLoading, refetch } = useQuery({ queryKey: ['capture-readiness'], queryFn: () => apiClient.getCaptureReadiness(), - refetchInterval: READINESS_POLL_INTERVAL_MS, - refetchOnWindowFocus: true, + // Poll only while a model is still missing/downloading. Once both are + // green the endpoint's answer can't change until the user swaps models + // in settings, and that path invalidates the query explicitly from + // useSettings. refetchOnWindowFocus stays gated to the same condition. + refetchInterval: (query) => { + const d = query.state.data; + return d && d.stt.ready && d.llm.ready ? false : READINESS_POLL_INTERVAL_MS; + }, + refetchOnWindowFocus: (query) => { + const d = query.state.data; + return !(d && d.stt.ready && d.llm.ready); + }, }); // On the web build there's no TCC layer — treat both as granted so the