Pair every daily-read invalidation with its inactive refetch

Ten client mutation sites forgot a consumer: a coach-accepted checkup
stayed invisible for up to five minutes, a threshold or target edit left
the dashboard bands stale, a score-config save marked the daily reads
stale but never refetched them, a booked visit missed the Today rail, a
source-priority reorder kept every chart on the old canonical picks, an
adopted self-context note never reached the Settings read. Each site now
invalidates what its write changed and forces the unmounted snapshot +
digest reads to refetch through refetchInactiveDailyReads.

New illnessDependentKeys bundle carries the daily reads (Rest Mode
frames both), dailyDigest joins encounterDependentKeys, and the
chart-data prefix gains a factory accessor for whole-cache flushes.

The daily-reads guard learns the cycle / encounter / vaccination /
illness bundle families and a second matcher for direct snapshot/digest
invalidateQueries without a forced refetch, each with a frozen reasoned
allowlist. Both matchers were proven live by reverting a fix and
watching the guard go red (see the test doc comment).
This commit is contained in:
Marc-André Bombeck committed 2026-08-13 18:48:10 +02:00
1 parent 002d120b69
commit f2f40ae8b2
17 files changed
+239 -24

No files matched your search

+14 -2
View File
@@ -11,7 +11,12 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { apiDelete, apiGet, apiPatch, apiPost } from "@/lib/api/api-fetch";
import { queryKeys } from "@/lib/query-keys";
import {
illnessDependentKeys,
invalidateKeys,
queryKeys,
refetchInactiveDailyReads,
} from "@/lib/query-keys";
import type {
IllnessCorrelationResponse,
@@ -119,7 +124,14 @@ export function useIllnessDayLogList(
function useInvalidateIllness() {
const qc = useQueryClient();
return () => qc.invalidateQueries({ queryKey: queryKeys.illness() });
// An episode write can flip Rest Mode, which frames the dashboard hero and
// the Today digest — both unmounted from here, so the bundle invalidation
// is paired with the forced inactive refetch. The write routes hard-evict
// the server analytics bucket, so the refetch returns post-write context.
return async () => {
await invalidateKeys(qc, illnessDependentKeys);
await refetchInactiveDailyReads(qc);
};
}
/** Create an episode. */