perf(analytics): keep closed blocks of past readings cached across syncs

Every sync marked all of an account's analytics cells stale, so the slice
re-read the pre-fold remainder (every reading older than five years,
folded per source and day, the slice's largest statement on a long
history) and the day view re-read its past history blocks, although a
sync of today's readings cannot change either.

A cache key can now name the instant its value's readings end before
(closedBlockKeyPart). invalidateUserMeasurements takes touchedFrom, the
earliest measuredAt a write created, changed or removed, and leaves such
blocks in place when it is not earlier; without it every block goes as
before. The batch route passes it from the identities it wrote. The
pre-fold remainder moves into its own module and is cached as a closed
block; the day view's past history blocks carry their end, with a day of
margin for a night across midnight.

The batch route's two up-front reads move into batch-stored-rows.ts with
the once-per-batch key rule they share.
This commit is contained in:
Marc-André Bombeck committed 2026-10-22 07:24:59 +02:00
1 parent 901cd884e8
commit f5d6710670
12 files changed
+493 -279

No files matched your search

@@ -1,12 +1,12 @@
{
"$comment": "Production files over 800 lines and their length. Maintained by src/__tests__/source-size-ratchet.test.ts.",
"count": 129,
"total": 156466,
"total": 156380,
"entries": {
"app/api/dashboard/summary/route.ts": 1032,
"app/api/documents/inbound/route.ts": 811,
"app/api/insights/generate/route.ts": 1209,
"app/api/measurements/batch/route.ts": 1576,
"app/api/measurements/batch/route.ts": 1569,
"app/api/measurements/route.ts": 938,
"app/api/measurements/series/route.ts": 879,
"app/api/medications/[id]/route.ts": 1281,
@@ -52,11 +52,11 @@
"lib/ai/coach/types.ts": 1011,
"lib/ai/codex-client.ts": 1094,
"lib/ai/prompts/insight-generator.ts": 1121,
"lib/ai/provider.ts": 1644,
"lib/ai/provider.ts": 1632,
"lib/ai/safety/outbound-screen.ts": 1463,
"lib/analytics/score/reader.ts": 998,
"lib/analytics/sleep-night.ts": 1345,
"lib/analytics/summaries-slice.ts": 1314,
"lib/analytics/summaries-slice.ts": 1248,
"lib/api-handler.ts": 1978,
"lib/auth/session.ts": 811,
"lib/cache/server-cache.ts": 851,
@@ -110,7 +110,7 @@
"lib/jobs/reminder/register-status.ts": 878,
"lib/managed-profiles/handover.ts": 986,
"lib/mcp/record-search.ts": 1467,
"lib/mcp/rich-reads.ts": 1468,
"lib/mcp/rich-reads.ts": 1467,
"lib/mcp/tools.ts": 2654,
"lib/measurements/dense-intraday-retention.ts": 1057,
"lib/measurements/import-apple-health-export.ts": 1729,
@@ -1,7 +1,7 @@
{
"$comment": "Production functions over 200 lines, keyed \"file :: name\", and their length. Maintained by src/__tests__/source-size-ratchet.test.ts.",
"count": 415,
"total": 154643,
"total": 154564,
"entries": {
"app/achievements/page.tsx :: AchievementsPage": 206,
"app/api/admin/backups/upload/route.ts :: apiHandler(arg)": 314,
@@ -38,7 +38,7 @@
"app/api/mcp/oauth/token/route.ts :: POST > withBackgroundEvent(arg)": 248,
"app/api/measurement-reminders/[id]/route.ts :: apiHandler(arg) #2": 240,
"app/api/measurements/[id]/route.ts :: apiHandler(arg) #2": 203,
"app/api/measurements/batch/route.ts :: postBatch": 1277,
"app/api/measurements/batch/route.ts :: postBatch": 1262,
"app/api/measurements/route.ts :: apiHandler(arg)": 286,
"app/api/measurements/route.ts :: postMeasurement": 377,
"app/api/measurements/series/route.ts :: apiHandler(arg)": 670,
@@ -299,7 +299,7 @@
"lib/analytics/correlations-fast-path.ts :: computeCorrelationHypothesesFastPath": 256,
"lib/analytics/intraday-pulse-io.ts :: loadIntradayPulse": 206,
"lib/analytics/score/reader.ts :: computeUserHealthScore": 324,
"lib/analytics/summaries-slice.ts :: computeFromRollups": 441,
"lib/analytics/summaries-slice.ts :: computeFromRollups": 377,
"lib/api-handler.ts :: apiHandler": 207,
"lib/api-handler.ts :: apiHandler > wrapped": 201,
"lib/auth/profile-update.ts :: applyProfileUpdate": 353,
@@ -1,7 +1,7 @@
{
"$comment": "Comment lines that open with a release version, per file under src/. Maintained by src/__tests__/version-stamp-ratchet.test.ts.",
"count": 2962,
"total": 10592,
"total": 10591,
"entries": {
"__tests__/account-payload-consumer-guard.test.ts": 2,
"__tests__/acting-account-boundary-guard.test.ts": 7,
@@ -1885,7 +1885,7 @@
"lib/analytics/sleep-night.ts": 3,
"lib/analytics/source-priority.ts": 2,
"lib/analytics/source-rank-sql.ts": 3,
"lib/analytics/summaries-slice.ts": 37,
"lib/analytics/summaries-slice.ts": 36,
"lib/analytics/trend-delta.ts": 1,
"lib/analytics/trends.ts": 6,
"lib/analytics/value-bands.ts": 1,