mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 05:42:19 +00:00
feat(insights): drop the per-metric assessment cache on fresh measurements
Hang `invalidateStatusInsightsForTypes` off every measurement ingest path so a new reading of a type drops the cached assessment rows that reading dirties — the next mount or nightly warm pass then regenerates them against the new data instead of serving the pre-measurement text for the rest of the day. Wired into both `/api/measurements` modes (single + multi-entry batch), `/api/measurements/batch`, and the three Withings sync paths (measures + activity + sleep), reusing the `collapseToTypeDayKeys` result each already computes for its rollup recompute. The call is fire-and-forget after the user's write commits: idempotent, never a blocker on the request path, and a failure only warns.
This commit is contained in:
1 parent
177ce576d3
commit
cd8849cd51
6 files changed
+153
No files matched your search
@@ -46,6 +46,7 @@ import { deviceTypeEnum } from "@/lib/validations/source-priority";
|
||||
import { checkRateLimit } from "@/lib/rate-limit";
|
||||
import { enqueuePrDetection } from "@/lib/jobs/pr-detection";
|
||||
import { invalidateUserMeasurements } from "@/lib/cache/invalidate";
|
||||
import { invalidateStatusInsightsForTypes } from "@/lib/insights/comprehensive-generate";
|
||||
import {
|
||||
recomputeBucketsForMeasurement,
|
||||
collapseToTypeDayKeys,
|
||||
@@ -484,6 +485,17 @@ async function postBatch(request: NextRequest): Promise<Response> {
|
||||
for (const k of insertedKeys) {
|
||||
await recomputeBucketsForMeasurement(user.id, k.type, k.measuredAt);
|
||||
}
|
||||
|
||||
// v1.8.0 — drop the cached per-metric assessment rows the ingested
|
||||
// types dirty so the next mount / nightly warm pass regenerates
|
||||
// them against the new data instead of serving stale text.
|
||||
// Fire-and-forget: never a blocker on the user's ingest.
|
||||
invalidateStatusInsightsForTypes(
|
||||
user.id,
|
||||
insertedKeys.map((k) => k.type),
|
||||
).catch((err) => {
|
||||
console.warn("[measurements] status-insight invalidate failed", err);
|
||||
});
|
||||
} catch (err) {
|
||||
console.warn("[measurements] rollup recompute failed", err);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
} from "@/lib/measurements/drain-per-sample-cumulative";
|
||||
import { withIdempotency } from "@/lib/idempotency";
|
||||
import { invalidateUserMeasurements } from "@/lib/cache/invalidate";
|
||||
import { invalidateStatusInsightsForTypes } from "@/lib/insights/comprehensive-generate";
|
||||
import {
|
||||
recomputeBucketsForMeasurement,
|
||||
collapseToTypeDayKeys,
|
||||
@@ -664,6 +665,16 @@ async function postMeasurement(request: NextRequest) {
|
||||
for (const k of keys) {
|
||||
await recomputeBucketsForMeasurement(user.id, k.type, k.measuredAt);
|
||||
}
|
||||
|
||||
// v1.8.0 — drop the cached per-metric assessment rows the ingested
|
||||
// types dirty so the next mount / nightly warm pass regenerates
|
||||
// them against the new data. Fire-and-forget: never blocks ingest.
|
||||
invalidateStatusInsightsForTypes(
|
||||
user.id,
|
||||
keys.map((k) => k.type),
|
||||
).catch((err) => {
|
||||
console.warn("[measurements] status-insight invalidate failed", err);
|
||||
});
|
||||
} catch (err) {
|
||||
console.warn("[measurements] rollup recompute failed", err);
|
||||
}
|
||||
@@ -768,5 +779,12 @@ async function postMeasurement(request: NextRequest) {
|
||||
console.warn("[measurements] rollup recompute failed", err);
|
||||
}
|
||||
|
||||
// v1.8.0 — drop the cached per-metric assessment rows this type
|
||||
// dirties so the next mount / nightly warm pass regenerates against
|
||||
// the new row. Fire-and-forget: never blocks the user's write.
|
||||
invalidateStatusInsightsForTypes(user.id, [measurement.type]).catch((err) => {
|
||||
console.warn("[measurements] status-insight invalidate failed", err);
|
||||
});
|
||||
|
||||
return apiSuccess(measurement, 201);
|
||||
}
|
||||
Reference in new issue
Block a user