github MBombeck/HealthLog v1.4.35
v1.4.35 — Persistent measurement rollups + partial read-swap

latest releases: v1.4.36, v1.4.35.1
6 hours ago

Foundation release for the persistent measurement_rollups cache tier. Adds a new additive table, populates it from every write path, and switches two reader surfaces onto it for the linearly-composable stats.

Highlights

  • New measurement_rollups table keyed on (user_id, type, granularity, bucket_start) carrying count / mean / min_value / max_value / sd / slope / r2 / computed_at. Additive only — migration 0067_v1434_measurement_rollups is idempotent under re-run.
  • Write hooks fold the DAY bucket synchronously on every measurement create / update / delete; WEEK / MONTH / YEAR follow on a pg-boss queue (rollup-recompute, concurrency = 2, singleton-keyed per bucket so burst writes coalesce).
  • Apple Health import worker calls recomputeUserRollups once at completion instead of per-row, scoped to the import's date range — a 100k-sample backfill no longer spawns 100k write hooks.
  • Reader surfaces (comprehensive-aggregator, summaries-slice) source count / min / max / mean per type from the DAY buckets via aggregateBuckets, plus the comprehensive dailyByType correlation feed straight from the bucket means. Slope / R² / standard deviation / anomaly counts continue to run against live SQL — they don't compose across DAY buckets.
  • Defensive parity check: the composed count is compared against the live aggregate's COUNT(*); on divergence the reader transparently falls back to live SQL. Covers cold-mount edge cases and the all-time-window degradation on accounts that never ran the backfill.
  • scripts/backfill-rollups.ts for the one-shot historical fold (--user <id> or every account). Single-user serial so the Prisma pool stays out of contention. Idempotent.

Tests

  • 3 new integration cases in tests/integration/measurement-rollups.test.ts pin the parity contract end-to-end against a real Postgres testcontainer: the aggregator's count / min / max / mean matches live SQL byte-for-byte, dailyByType matches a parallel date_trunc('day', ...) GROUP BY query, and a freshly-written measurement is reflected on the next read.
  • Unit suite: 4249 → 4280. Integration suite: 222 → 228. pnpm typecheck + pnpm lint clean.

Operator notes

  • Coolify auto-pulls via the v1.4.34.2 pull_policy: always directive — no manual retag needed.
  • Run pnpm tsx scripts/backfill-rollups.ts once post-deploy to fold the trailing history into all four granularities. Idempotent under re-run.

A full read-swap across every analytics surface is planned for a follow-up release once the partial swap has proven itself in production.

Don't miss a new HealthLog release

NewReleases is sending notifications on new releases.