perf(rollups): fold weekly, monthly and yearly buckets from canonical days in SQL

Building the coarse buckets from the DAY tier read every day of the window
into the process: a five-year yearly read moved thousands of rows per type,
and the Coach's history bands read several such windows per request. The
per-day source pick and the fold now run in Postgres (DISTINCT ON the day,
ordered by the ladder rank and then the source name, the same order the
in-process pick uses), so a coarse read returns one row per bucket. The
long-range chart picks its tier from the span of the window's days and reads
that tier once. The Coach snapshot hands its already-loaded source order to
the history bands instead of each band reading it again.
This commit is contained in:
Marc-André Bombeck committed 2026-09-26 16:56:02 +02:00
1 parent ff4aa32f6d
commit 7860df2fba
14 files changed
+563 -423

No files matched your search

@@ -20,6 +20,7 @@ import {
recomputeUserRollups,
} from "@/lib/rollups/measurement-rollups";
import { readLiveBuckets } from "@/lib/measurements/daily-series-read";
import { readTieredRollupSeries } from "@/lib/rollups/measurement-read-wmy";
import { readAllTimeExtremes } from "@/lib/insights/feature-blocks";
import { computeSummariesSlice } from "@/lib/analytics/summaries-slice";
import type { MeasurementType } from "@/generated/prisma/client";
@@ -366,4 +367,58 @@ describe("coarse buckets — canonical source per day", () => {
expect(slice.summaries.WEIGHT.max).toBe(90);
expect(slice.summaries.WEIGHT.mean).toBe(86);
});
it("the long-range chart and the yearly router fold the same canonical days", async () => {
const user = await seedUser();
const rows: Row[] = [];
// Two years of blood pressure: typed in every tenth day, a synced cuff
// (higher on the ladder) on every thirtieth day, both on some days.
const start = Date.UTC(2024, 0, 1, 8);
for (let i = 0; i < 730; i += 10) {
rows.push({
type: "BLOOD_PRESSURE_SYS",
source: "MANUAL",
value: 150,
at: new Date(start + i * DAY_MS),
});
if (i % 30 === 0) {
rows.push({
type: "BLOOD_PRESSURE_SYS",
source: "WITHINGS",
value: 120,
at: new Date(start + i * DAY_MS + 3_600_000),
});
}
}
await getPrismaClient().measurement.createMany({
data: rows.map((r) => ({
userId: user.id,
type: r.type,
value: r.value,
unit: "mmHg",
source: r.source,
measuredAt: r.at,
})),
});
await recomputeUserRollups(user.id, {
from: new Date("2023-12-01T00:00:00.000Z"),
to: new Date("2026-02-01T00:00:00.000Z"),
granularities: ["DAY"],
});
const tiered = await readTieredRollupSeries({
userId: user.id,
type: "BLOOD_PRESSURE_SYS",
from: new Date("2016-01-01T00:00:00.000Z"),
to: new Date("2026-01-31T00:00:00.000Z"),
priorityJson: null,
});
expect(tiered?.granularity).toBe("WEEK");
// Every seeded day counts once, with the cuff winning the shared days.
const days = 73;
const cuffDays = 25;
expect(tiered?.rows.reduce((n, r) => n + r.count, 0)).toBe(days);
const total = tiered?.rows.reduce((n, r) => n + r.value * r.count, 0) ?? 0;
expect(total).toBeCloseTo((days - cuffDays) * 150 + cuffDays * 120, 6);
});
});