Marc-André Bombeck
c1811bc85b
Stop narrating rollup buckets the record cannot account for
...
A rollup band outlives the rows it was folded from. The read-swap falls back to
live SQL only when a band is EMPTY, so a bucket that is merely wrong is served
as current; `ensureUserRollupsFresh` repairs the DAY tier over the trailing 90
days only, and keys off `Measurement.updatedAt`, which a hard delete does not
bump. The WHOOP body sync hard-deletes a WEIGHT row with no invalidation, so a
MONTH bucket keeps reporting a value the record no longer holds.
The block was handing the model two irreconcilable accounts of the same record
and marking neither: the coarse tail said one thing, the all-time extremes read
live beside it said another, and `asOf` stamped the whole thing current because
it is derived from raw reading age and knows nothing about rollup age.
Reconcile them where they are assembled. A bucket mean is an average of real
rows, so it cannot fall outside those rows' own all-time extremes — when it
does, the band is describing readings the live read cannot see. That is an
invariant rather than a heuristic, so the disputed tail is dropped and
`asOf.coarseHistoryWithheld` records that it went. Narrating a ghost is worse
than narrating less.
`currentForTodayClaims` stays keyed to raw recency, which is what it means. The
surviving readings really are from today, and suppressing a true present-tense
statement to punish a stale history band would trade one dishonesty for another.
The bucket on disk is still wrong, and a wide event now says so. The deeper fix
is to make the tier notice — compare a bucket's `computedAt` against the type's
in-window MAX(`updatedAt`), or invalidate on the hard-delete path — which is a
larger change than this repair.
2026-08-22 16:14:54 +02:00
..
2026-08-08 21:01:50 +02:00
2026-05-10 10:34:32 +02:00
2026-08-06 18:21:40 +02:00
2026-05-09 21:00:23 +02:00
2026-08-03 21:15:45 +02:00
2026-05-09 20:46:20 +02:00
2026-07-20 13:42:38 +02:00
2026-07-20 12:24:15 +02:00
2026-08-08 01:05:31 +02:00
2026-06-19 22:20:31 +02:00
2026-05-10 11:05:40 +02:00
2026-07-29 13:42:04 +02:00
2026-06-28 19:26:16 +02:00
2026-07-31 11:15:27 +02:00
2026-07-04 14:46:19 +02:00
2026-05-16 19:46:43 +02:00
2026-05-14 23:49:32 +02:00
2026-08-06 14:10:28 +02:00
2026-07-29 14:20:56 +02:00
2026-07-16 08:48:41 +02:00
2026-07-21 13:08:28 +02:00
2026-07-28 23:02:00 +02:00
2026-07-22 04:14:15 +02:00
2026-07-19 11:41:12 +02:00
2026-07-19 11:40:56 +02:00
2026-07-18 02:09:33 +02:00
2026-07-28 00:09:22 +02:00
2026-07-31 07:37:48 +02:00
2026-08-22 00:01:52 +02:00
2026-08-22 11:51:52 +02:00
2026-08-02 09:04:36 +02:00
2026-08-14 02:33:07 +02:00
2026-06-28 14:00:55 +02:00
2026-07-20 00:40:20 +02:00
2026-06-14 14:26:58 +02:00
2026-06-19 22:20:31 +02:00
2026-06-27 22:40:01 +02:00
2026-06-27 20:37:35 +02:00
2026-05-10 11:05:40 +02:00
2026-07-21 01:34:29 +02:00
2026-07-26 18:34:42 +02:00
2026-06-19 22:20:31 +02:00
2026-06-26 14:17:36 +02:00
2026-07-16 23:32:28 +02:00
2026-05-10 16:11:12 +02:00
2026-05-11 02:38:17 +02:00
2026-07-24 18:28:41 +02:00
2026-08-07 16:29:58 +02:00
2026-08-22 16:14:54 +02:00
2026-06-01 19:54:26 +02:00
2026-07-15 22:49:07 +02:00
2026-08-13 22:07:57 +02:00
2026-07-25 21:57:06 +02:00
2026-08-08 01:02:08 +02:00
2026-08-02 09:04:36 +02:00
2026-08-08 01:02:08 +02:00
2026-08-07 15:03:10 +02:00
2026-07-20 00:40:20 +02:00
2026-08-03 09:52:02 +02:00
2026-07-17 14:29:07 +02:00
2026-07-17 14:29:07 +02:00
2026-07-20 12:24:15 +02:00
2026-08-08 14:27:36 +02:00
2026-08-08 14:27:36 +02:00
2026-07-08 22:05:05 +02:00
2026-07-22 04:14:15 +02:00
2026-07-21 13:08:28 +02:00
2026-08-01 19:35:16 +02:00
2026-08-01 19:26:47 +02:00
2026-08-10 05:32:58 +02:00
2026-08-10 05:32:59 +02:00
2026-08-08 12:20:19 +02:00
2026-08-08 15:06:10 +02:00
2026-08-08 15:54:19 +02:00
2026-07-21 00:36:40 +02:00
2026-05-10 00:11:36 +02:00
2026-06-22 09:00:39 +02:00
2026-06-22 09:00:39 +02:00
2026-07-19 13:40:03 +02:00
2026-07-21 00:36:40 +02:00
2026-07-29 14:18:20 +02:00
2026-07-29 14:22:49 +02:00
2026-08-07 06:11:36 +02:00
2026-08-10 05:32:59 +02:00
2026-08-01 17:56:20 +02:00
2026-08-12 22:52:03 +02:00
2026-07-31 16:48:40 +02:00
2026-08-07 14:16:17 +02:00
2026-08-06 01:29:07 +02:00
2026-05-09 18:08:11 +02:00
2026-06-19 22:20:31 +02:00
2026-05-10 01:30:06 +02:00
2026-05-10 11:05:40 +02:00
2026-06-28 19:23:57 +02:00
2026-06-19 22:20:31 +02:00
2026-08-07 14:03:09 +02:00
2026-07-07 15:55:50 +02:00
2026-06-19 22:20:31 +02:00
2026-06-11 02:19:28 +02:00
2026-07-27 14:35:34 +02:00
2026-07-28 14:00:44 +02:00
2026-07-27 14:35:33 +02:00
2026-07-26 18:02:35 +02:00
2026-07-26 14:37:57 +02:00
2026-07-29 15:59:27 +02:00
2026-08-07 21:40:41 +02:00
2026-08-08 14:05:58 +02:00
2026-08-06 02:36:08 +02:00
2026-08-07 05:24:11 +02:00
2026-08-07 05:11:02 +02:00
2026-07-29 15:59:12 +02:00
2026-08-14 03:56:38 +02:00
2026-07-25 15:03:44 +02:00
2026-06-19 22:20:31 +02:00
2026-06-19 22:20:31 +02:00
2026-07-28 15:12:23 +02:00
2026-05-16 10:59:42 +02:00
2026-05-31 14:36:17 +02:00
2026-07-25 15:03:44 +02:00
2026-08-06 20:56:16 +02:00
2026-06-19 22:20:31 +02:00
2026-07-26 00:45:08 +02:00
2026-06-19 22:20:31 +02:00
2026-06-10 11:18:00 +02:00
2026-08-06 02:00:35 +02:00
2026-08-06 02:00:35 +02:00
2026-08-06 02:00:35 +02:00
2026-08-10 07:58:48 +02:00
2026-08-07 06:02:31 +02:00
2026-07-29 15:59:12 +02:00
2026-06-19 22:20:31 +02:00
2026-07-25 18:41:40 +02:00
2026-06-27 19:56:30 +02:00
2026-08-06 18:54:20 +02:00
2026-08-08 01:03:05 +02:00
2026-08-08 07:14:04 +02:00
2026-08-08 09:58:22 +02:00
2026-08-08 09:58:50 +02:00
2026-08-08 15:30:38 +02:00
2026-06-14 11:31:52 +02:00
2026-06-05 03:45:04 +02:00
2026-06-27 19:33:10 +02:00
2026-06-19 22:20:31 +02:00
2026-08-08 15:30:00 +02:00
2026-07-28 14:01:11 +02:00
2026-08-08 03:03:38 +02:00
2026-06-27 19:33:10 +02:00
2026-08-06 13:47:42 +02:00
2026-07-30 23:30:28 +02:00
2026-07-25 11:36:18 +02:00
2026-07-29 13:55:57 +02:00
2026-07-27 23:15:38 +02:00
2026-08-09 06:53:57 +02:00
2026-07-26 14:37:57 +02:00
2026-07-22 04:14:15 +02:00
2026-07-19 02:31:45 +02:00
2026-05-08 17:46:31 +02:00
2026-08-06 17:52:10 +02:00
2026-08-06 19:33:15 +02:00
2026-08-06 18:21:40 +02:00
2026-08-06 03:52:49 +02:00
2026-07-29 13:42:04 +02:00
2026-07-14 11:56:29 +02:00
2026-06-26 13:24:30 +02:00
2026-06-19 22:20:31 +02:00
2026-07-23 15:16:48 +02:00
2026-07-19 13:48:46 +02:00
2026-05-21 23:13:21 +02:00
2026-08-08 01:05:31 +02:00
2026-08-06 18:54:20 +02:00
2026-07-07 22:00:14 +02:00
2026-08-08 18:02:21 +02:00
2026-08-14 02:33:07 +02:00
2026-08-22 13:04:33 +02:00
2026-08-07 00:01:27 +02:00
2026-08-06 18:54:20 +02:00
2026-08-07 06:11:36 +02:00
2026-08-07 06:11:36 +02:00
2026-08-07 06:11:36 +02:00
2026-08-14 14:27:58 +02:00
2026-08-07 06:11:36 +02:00
2026-08-06 18:54:20 +02:00
2026-08-05 23:58:30 +02:00
2026-08-07 14:30:10 +02:00
2026-07-26 14:04:44 +02:00
2026-06-04 10:05:47 +02:00
2026-07-29 16:08:41 +02:00
2026-07-15 22:49:07 +02:00
2026-07-31 01:12:22 +02:00
2026-08-03 10:34:48 +02:00
2026-08-02 02:00:08 +02:00
2026-07-22 04:14:15 +02:00
2026-06-19 22:20:31 +02:00
2026-08-08 21:01:25 +02:00
2026-08-08 14:36:08 +02:00
2026-08-08 23:00:39 +02:00
2026-06-05 08:10:13 +02:00
2026-07-22 04:14:15 +02:00
2026-08-08 01:05:31 +02:00
2026-05-17 15:36:38 +02:00
2026-07-18 02:30:33 +02:00
2026-05-24 22:22:30 +02:00
2026-05-14 23:49:32 +02:00
2026-05-17 15:36:38 +02:00
2026-07-22 04:14:15 +02:00
2026-08-08 09:53:09 +02:00
2026-07-22 04:14:15 +02:00
2026-08-13 10:25:39 +02:00
2026-07-20 00:40:20 +02:00