mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +00:00
fix(rollups): skip soft-deleted measurements in DAY recompute
The `runRollupAggregate` SQL folded every row in `measurements` regardless of `deleted_at`. Once iOS soft-deletes its first reading through the by-external-ids path, the tombstoned value would still contribute to the bucket count / mean / min / max, leaving dashboards and analytics showing data the user thinks they removed. Add `AND m."deleted_at" IS NULL` to both branches of `runRollupAggregate` plus the watermark probes in `isRollupFresh` and `ensureUserRollupsFreshImpl` so a stale `updatedAt` on a tombstoned row no longer keeps the rollup flagged as stale forever. The boot-time backfill discovery is widened the same way so deleted-only `(user, type, day)` tuples never enqueue. Defense-in-depth: every reader will pick up the filter in follow-up commits — this lands the writer-side cut so newly-folded buckets are already clean.
This commit is contained in:
1 parent
433874e390
commit
db2d864a8e
1 file changed
+5
-2
@@ -319,7 +319,7 @@ export async function isRollupFresh(
|
||||
newestComputedAt: Date | null,
|
||||
): Promise<boolean> {
|
||||
const newest = await prisma.measurement.findFirst({
|
||||
where: { userId, type },
|
||||
where: { userId, type, deletedAt: null },
|
||||
orderBy: { measuredAt: "desc" },
|
||||
select: { measuredAt: true, updatedAt: true },
|
||||
});
|
||||
@@ -403,6 +403,7 @@ async function runRollupAggregate(input: {
|
||||
AND m."type" IN (${typeList})
|
||||
AND m."measured_at" >= $2
|
||||
AND m."measured_at" < $3
|
||||
AND m."deleted_at" IS NULL
|
||||
GROUP BY m."type", ${dateTrunc}
|
||||
`;
|
||||
return prisma.$queryRawUnsafe<RollupRow[]>(
|
||||
@@ -435,6 +436,7 @@ async function runRollupAggregate(input: {
|
||||
WHERE m."user_id" = $1
|
||||
AND m."measured_at" >= $2
|
||||
AND m."measured_at" < $3
|
||||
AND m."deleted_at" IS NULL
|
||||
GROUP BY m."type", ${dateTrunc}
|
||||
`;
|
||||
return prisma.$queryRawUnsafe<RollupRow[]>(
|
||||
@@ -656,7 +658,7 @@ async function ensureUserRollupsFreshImpl(
|
||||
select: { computedAt: true },
|
||||
}),
|
||||
prisma.measurement.findFirst({
|
||||
where: { userId },
|
||||
where: { userId, deletedAt: null },
|
||||
orderBy: { updatedAt: "desc" },
|
||||
select: { updatedAt: true, measuredAt: true },
|
||||
}),
|
||||
@@ -775,6 +777,7 @@ export async function enqueueBootTimeRollupBackfill(): Promise<{
|
||||
m."type",
|
||||
date_trunc('day', m."measured_at") AS bucket_start
|
||||
FROM measurements m
|
||||
WHERE m."deleted_at" IS NULL
|
||||
) mt
|
||||
LEFT JOIN measurement_rollups r
|
||||
ON r."user_id" = mt."user_id"
|
||||
|
||||
Reference in new issue
Block a user