fix(dashboard): hard-evict snapshot on background sync paths

The in-app measurement routes evict the snapshot cache, but the iOS
batch ingest and the server-side Withings sync only marked it stale (or
never touched it), so a focus-refetch could serve pre-sync data for up
to the snapshot TTL. Route both background-sync entry points through a
hard evict so returning to the dashboard surfaces freshly-synced rows.
This commit is contained in:
Marc-André Bombeck committed 2026-06-20 12:51:58 +02:00
1 parent 773e4ec4d5
commit 375d5c3ec5
2 files changed
+16 -1

No files matched your search

+6 -1
View File
@@ -648,7 +648,12 @@ async function postBatch(request: NextRequest): Promise<Response> {
// and must invalidate every consumer that reads through this user's
// measurements.
if (insertedCount > 0 || updatedCount > 0) {
invalidateUserMeasurements(user.id);
// v1.18.9 (#38) — hard-evict so a focus-refetch after a background
// iOS / Apple-Health batch sync returns post-sync data. A mark-stale
// would let the `cachedSwr` snapshot serve the pre-batch body on the
// very next read, leaving the dashboard up to ~180 s stale; the manual
// measurement routes already pass `{ evict: true }` for the same reason.
invalidateUserMeasurements(user.id, { evict: true });
// v1.5.0 — refresh the persistent rollup table for every distinct
// (type, day) the batch touched. We use the `prepared` rows
+10
View File
@@ -29,6 +29,7 @@ import {
recomputeBucketsForMeasurement,
} from "@/lib/rollups/measurement-rollups";
import { invalidateStatusInsightsForTypes } from "@/lib/insights/comprehensive-generate";
import { invalidateUserDashboardSnapshot } from "@/lib/cache/invalidate";
/**
* Build the callback URL handed to Withings at `Notify.subscribe` time.
@@ -264,6 +265,15 @@ export async function syncUserMeasurements(
`withings: status-insight invalidate failed for ${userId}: ${err}`,
);
});
// v1.18.9 (#38) — hard-evict the dashboard snapshot so a focus-refetch
// after this server-side sync returns the freshly-imported readings.
// The server-side Withings path produces no client mutation event, so
// without this the snapshot's `cachedSwr` entry kept serving the
// pre-sync body until its ~180 s TTL lapsed.
if (keys.length > 0) {
invalidateUserDashboardSnapshot(userId);
}
} catch (err) {
getEvent()?.addWarning(
`withings: rollup recompute failed for ${userId}: ${err}`,