fix(mood): bound the mood series fallback to the rollup window

Without mood rollups the series walked every mood entry the account ever
logged, while the rollup path reads the trailing five years. The live
fallback now reads the same window.
This commit is contained in:
Marc-André Bombeck committed 2026-10-20 04:37:15 +02:00
1 parent 9ffcdea312
commit 2861075676
2 files changed
+17 -3

No files matched your search

@@ -83,6 +83,19 @@ describe("buildMoodDailySeries", () => {
expect(series.summary.count).toBe(2);
});
it("bounds the live walk to the window the rollup read covers", async () => {
await buildMoodDailySeries("user-1");
const [rollupUser, since] = vi.mocked(readMoodDayRollups).mock.calls[0] as [
string,
Date,
];
expect(rollupUser).toBe("user-1");
const args = vi.mocked(prisma.moodEntry.findMany).mock.calls[0]?.[0] as {
where: { moodLoggedAt?: { gte: Date } };
};
expect(args.where.moodLoggedAt?.gte).toEqual(since);
});
it("returns an empty series for a user with no rollups and no raw entries", async () => {
const series = await buildMoodDailySeries("user-1");
expect(series.entries).toEqual([]);
+4 -3
View File
@@ -116,11 +116,12 @@ export async function buildMoodDailySeries(
return { entries, summary, entryCount, source: "rollup" };
}
// Coverage fallback — no rollup rows yet. Run the legacy live walk ONCE;
// the warm-up above mints the rollups for the next request.
// Coverage fallback — no rollup rows yet. Run the live walk ONCE over the
// same window the rollup read covers; the warm-up above mints the rollups
// for the next request.
const moodEntries = await client.moodEntry.findMany({
// v1.7.0 sync — exclude tombstoned rows from the fallback.
where: { userId, deletedAt: null },
where: { userId, deletedAt: null, moodLoggedAt: { gte: since } },
orderBy: { moodLoggedAt: "asc" },
select: { date: true, score: true },
});