mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 22:02:16 +00:00
fix(insights): stop warming every assessment on an overview visit
Opening the Insights overview fired a once-per-session background warm that forced the provider to regenerate the comprehensive briefing and every category and metric assessment at once — a multi-minute burst that contended with foreground requests and made the app feel unresponsive until it finished. The nightly pass keeps the caches warm and the per-metric status GETs revalidate gently on their own, so the warm-on-mount is redundant. Remove it; the manual 'prepare assessments' button remains the explicit on-demand re-warm.
This commit is contained in:
1 parent
ed5d453431
commit
879833b372
2 files changed
+13
-52
No files matched your search
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import dynamic from "next/dynamic";
|
||||
import Link from "next/link";
|
||||
@@ -152,16 +151,12 @@ export default function InsightsPage() {
|
||||
const analyticsQuery = useAnalyticsQuery();
|
||||
const analytics = analyticsQuery.data as AnalyticsData | undefined;
|
||||
|
||||
// v1.8.7.1 — on-demand full assessment warm. The auto-trigger fires once
|
||||
// per session as soon as the overview confirms the user has data, so the
|
||||
// status cards (and the iOS client, which reads the same routes) land on
|
||||
// warm caches without the user waiting. The manual button below re-warms
|
||||
// everything on demand.
|
||||
const { warm, isWarming, autoWarmOnce } = useInsightsWarm();
|
||||
const hasData = !!data && data.totalMeasurements > 0;
|
||||
useEffect(() => {
|
||||
autoWarmOnce(isAuthenticated && hasData);
|
||||
}, [autoWarmOnce, isAuthenticated, hasData]);
|
||||
// The "prepare assessments" button below re-warms every assessment on
|
||||
// demand. There is no warm-on-mount: the nightly cron (04:30) keeps the
|
||||
// caches warm and the per-metric status GETs revalidate gently on their
|
||||
// own (stale-while-revalidate), so opening the overview only reads cached
|
||||
// text — it never fans out a full provider warm on a page visit.
|
||||
const { warm, isWarming } = useInsightsWarm();
|
||||
|
||||
// Empty-state shortcut — only paint once the comprehensive query has
|
||||
// resolved AND reported zero measurements. While it's in-flight we
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback, useRef } from "react";
|
||||
import { useCallback } from "react";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
|
||||
@@ -8,7 +8,7 @@ import { queryKeys } from "@/lib/query-keys";
|
||||
import { useTranslations } from "@/lib/i18n/context";
|
||||
|
||||
/**
|
||||
* v1.8.7.1 — on-demand full assessment warm.
|
||||
* On-demand full assessment warm.
|
||||
*
|
||||
* POSTs `/api/insights/pregenerate`, which enqueues a forced warm of every
|
||||
* AI assessment (comprehensive insight + the seven specialised status cards
|
||||
@@ -16,18 +16,13 @@ import { useTranslations } from "@/lib/i18n/context";
|
||||
* the worker and returns immediately. The cards then fill via their existing
|
||||
* stale-while-revalidate GETs — there is nothing to invalidate here.
|
||||
*
|
||||
* Two entry points share the one mutation:
|
||||
* - `warm()` — the manual "prepare assessments" button. Shows a toast.
|
||||
* - `autoWarmOnce(enabled)` — a fire-and-forget background warm fired ONCE
|
||||
* per browser session (sessionStorage-gated) when the Insights overview
|
||||
* mounts with data, so a returning user lands on warm caches without
|
||||
* tapping anything. The auto path is silent (no toast) and tolerates a
|
||||
* blocked/failed request — the server-side anti-spam bucket and the
|
||||
* nightly cron are the catch-net.
|
||||
* This is the explicit "prepare assessments" button only. There is no
|
||||
* warm-on-mount: the nightly cron (04:30 Europe/Berlin) keeps every user's
|
||||
* caches warm, and the per-metric status GETs revalidate gently on their
|
||||
* own — so a page visit reads cached text instead of fanning out a full
|
||||
* provider warm that would contend with foreground requests.
|
||||
*/
|
||||
|
||||
const AUTO_WARM_SESSION_KEY = "healthlog:insights:auto-warm";
|
||||
|
||||
async function postWarm(): Promise<void> {
|
||||
// Same-origin relative-path fetch — exempt from the safe-fetch rule by
|
||||
// construction. A 429 (warm already in progress) is an expected,
|
||||
@@ -47,12 +42,6 @@ export interface UseInsightsWarmResult {
|
||||
warm: () => void;
|
||||
/** True while the warm POST is in flight. */
|
||||
isWarming: boolean;
|
||||
/**
|
||||
* Fire the background warm once per session. Pass `enabled` (e.g.
|
||||
* authenticated AND the user has data) — the warm only fires on the
|
||||
* first call where `enabled` is true, and never again this session.
|
||||
*/
|
||||
autoWarmOnce: (enabled: boolean) => void;
|
||||
}
|
||||
|
||||
export function useInsightsWarm(): UseInsightsWarmResult {
|
||||
@@ -71,31 +60,8 @@ export function useInsightsWarm(): UseInsightsWarmResult {
|
||||
});
|
||||
}, [mutate, t]);
|
||||
|
||||
// The auto-trigger must fire at most once per session even across the
|
||||
// remounts a route navigation causes. A ref guards within the mount;
|
||||
// sessionStorage guards across mounts / navigations.
|
||||
const firedThisMount = useRef(false);
|
||||
const autoWarmOnce = useCallback(
|
||||
(enabled: boolean) => {
|
||||
if (!enabled || firedThisMount.current) return;
|
||||
firedThisMount.current = true;
|
||||
try {
|
||||
if (window.sessionStorage.getItem(AUTO_WARM_SESSION_KEY)) return;
|
||||
window.sessionStorage.setItem(AUTO_WARM_SESSION_KEY, String(Date.now()));
|
||||
} catch {
|
||||
// sessionStorage can throw under strict-privacy modes — fall
|
||||
// through and fire the warm anyway; the server bucket de-dupes.
|
||||
}
|
||||
// Silent background warm — no toast, errors swallowed by the
|
||||
// mutation's default (no onError handler surfaces it).
|
||||
mutate();
|
||||
},
|
||||
[mutate],
|
||||
);
|
||||
|
||||
return {
|
||||
warm,
|
||||
isWarming: mutation.isPending,
|
||||
autoWarmOnce,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user