mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
fix(rollups): boot-backfill discovery SQL uses bucket_start as NULL sentinel
v1.4.38.5 referenced `r."id" IS NULL` on the LEFT JOIN — but `measurement_rollups` has a composite primary key `(user_id, type, granularity, bucket_start)` and no surrogate `id` column. Postgres rejected the query with `column r.id does not exist` (SQL state 42703); the worker boot swallowed the error per the helper's best-effort contract and the queue stayed empty. Net effect: v1.4.38.5 deployed cleanly but delivered none of its promised fast-path recovery. Marc's account stayed on the live aggregator. The fix uses `r."bucket_start" IS NULL` — any column from the unmatched right side of the LEFT JOIN serves the "no matching row" filter, and `bucket_start` is part of the composite PK so the planner already has the column. Bumps to v1.4.38.6.
This commit is contained in:
1 parent
9c13cba3f7
commit
7ce29899e0
3 files changed
+36
-6
No files matched your search
@@ -1,5 +1,34 @@
|
||||
# Changelog
|
||||
|
||||
## [1.4.38.6] — 2026-05-18 — Boot-backfill discovery SQL fix
|
||||
|
||||
The v1.4.38.5 discovery rewrite filtered the LEFT JOIN with
|
||||
`WHERE r."id" IS NULL` — but `measurement_rollups` has a composite
|
||||
primary key `(user_id, type, granularity, bucket_start)` and no
|
||||
surrogate `id` column. Postgres rejected the query with
|
||||
`column r.id does not exist` (SQL state 42703), the worker boot
|
||||
swallowed the error per the helper's best-effort contract, and the
|
||||
queue stayed empty. Net effect: v1.4.38.5 deployed cleanly but
|
||||
delivered none of its promised fast-path recovery.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Boot-backfill discovery now filters on `r."bucket_start" IS NULL`**
|
||||
— any column from the right side of the LEFT JOIN serves as the
|
||||
"no matching row" sentinel; `bucket_start` is part of the composite
|
||||
primary key so the planner already touches the column. Verified
|
||||
against the live schema: `42703` no longer raised on worker boot,
|
||||
and the discovery query returns the expected per-type-missing
|
||||
candidate set.
|
||||
|
||||
### Operator notes
|
||||
|
||||
- No new migration. No env-var change.
|
||||
- On first boot after deploy the rollup-full-backfill queue picks
|
||||
up users with any missing type-coverage and folds them. Power-
|
||||
user accounts may see one slow `/api/analytics` cold-mount before
|
||||
the next request lands on the restored fast path.
|
||||
|
||||
## [1.4.38.5] — 2026-05-18 — Analytics fast-path restored on long-running accounts
|
||||
|
||||
Hotfix on top of v1.4.38.4. `/api/analytics` and the dashboard
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "healthlog",
|
||||
"version": "1.4.38.5",
|
||||
"version": "1.4.38.6",
|
||||
"description": "Self-hosted personal-health-tracking PWA with Withings integration, AI insights, and doctor-report PDF export.",
|
||||
"license": "AGPL-3.0-only",
|
||||
"homepage": "https://healthlog.dev",
|
||||
|
||||
@@ -736,10 +736,11 @@ export async function enqueueBootTimeRollupBackfill(): Promise<{
|
||||
// planner uses the `(user_id, type, measured_at)` index path; the
|
||||
// LEFT JOIN onto `measurement_rollups` uses the
|
||||
// `(user_id, type, granularity, bucket_start)` composite primary
|
||||
// key. `r."id" IS NULL` filters the unmatched partitions. A user
|
||||
// surfaces here when ANY type is missing — including the brand-
|
||||
// new-type case that v1.4.35.1's zero-rollup-only shape silently
|
||||
// stranded.
|
||||
// key. `measurement_rollups` has no surrogate `id` column —
|
||||
// `r."bucket_start" IS NULL` (any column from the right side of
|
||||
// the LEFT JOIN) marks the unmatched partitions. A user surfaces
|
||||
// here when ANY type is missing — including the brand-new-type
|
||||
// case that v1.4.35.1's zero-rollup-only shape silently stranded.
|
||||
const users = await prisma.$queryRaw<Array<{ id: string }>>`
|
||||
SELECT DISTINCT mt."user_id" AS id
|
||||
FROM (
|
||||
@@ -750,7 +751,7 @@ export async function enqueueBootTimeRollupBackfill(): Promise<{
|
||||
ON r."user_id" = mt."user_id"
|
||||
AND r."type" = mt."type"
|
||||
AND r."granularity" = 'DAY'
|
||||
WHERE r."id" IS NULL
|
||||
WHERE r."bucket_start" IS NULL
|
||||
`;
|
||||
|
||||
if (users.length === 0) {
|
||||
|
||||
Reference in new issue
Block a user