mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 22:02:16 +00:00
Pure-history medication detail page, legacy step consolidation, and the finish of the outbound-fetch migration. - /medications/[id] becomes a read-only history surface; every setting moves into a new advanced-settings sheet, and the edit trigger becomes a two-option picker. The list page is unchanged. - A pg-boss job folds pre-v1.5.0 granular step rows into one canonical daily total per user per day and soft-deletes the originals; migration 0087 adds a partial index for the converging discovery scan. - Every remaining server-side fetch routes through safeFetch (Withings, Codex OAuth + SSE, bug-report, Umami, GlitchTip, Loki); a new healthlog/safe-fetch-required ESLint rule guards the boundary. - Fixes: intake-edit dialog seeded from real values, consolidation skips a unique-constraint day instead of stranding it, avatar upload reads the body once under a bounded cap, egress lint rejects absolute URLs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
39 lines
2.1 KiB
SQL
39 lines
2.1 KiB
SQL
-- v1.5.6 — accelerate the legacy step-consolidation discovery query.
|
|
--
|
|
-- The boot-time consolidation pass (`enqueueBootTimeStepConsolidation`
|
|
-- in src/lib/jobs/step-consolidation.ts) repeatedly scans for users
|
|
-- still holding live pre-v1.5.0 granular step rows: `ACTIVITY_STEPS`
|
|
-- rows that are not tombstoned and whose `external_id` is NULL or does
|
|
-- not carry the `stats:HKQuantityTypeIdentifierStepCount:` daily-total
|
|
-- prefix. On an account with a multi-year HealthKit history that
|
|
-- predicate matches hundreds-of-thousands of rows before the
|
|
-- consolidation tombstones them.
|
|
--
|
|
-- A partial index keyed on the legacy-candidate predicate keeps both
|
|
-- the per-boot discovery scan and the per-user `findMany` cheap, and —
|
|
-- because the index only covers `deleted_at IS NULL` rows — it shrinks
|
|
-- to (eventually) empty as the pass converges, so it carries no
|
|
-- steady-state write cost once every legacy row is consolidated.
|
|
--
|
|
-- Additive + order-safe: a pure `CREATE INDEX IF NOT EXISTS`, no column
|
|
-- add, no backfill, no rewrite of `measurements`.
|
|
--
|
|
-- Lock note (conscious trade-off): this is a plain, non-`CONCURRENTLY`
|
|
-- index build, so it runs inside Prisma's migration transaction and
|
|
-- holds an ACCESS EXCLUSIVE lock on `measurements` for the duration of
|
|
-- the build — reads and writes to the table block until it completes.
|
|
-- The `deleted_at IS NULL` + `type = 'ACTIVITY_STEPS'` partial predicate
|
|
-- keeps the index tiny (most tenants carry no legacy step rows at all,
|
|
-- and the covered set shrinks to empty as the pass converges), so on a
|
|
-- typical self-host the build is sub-second and the lock is not felt.
|
|
-- The largest multi-year HealthKit tenants are the ones who both need
|
|
-- this index and would feel a longer lock; for those, run the deploy at
|
|
-- a low-traffic window. A `CONCURRENTLY` build cannot run inside the
|
|
-- migration transaction and is not warranted given the partial-index
|
|
-- size on the overwhelming majority of deployments.
|
|
|
|
CREATE INDEX IF NOT EXISTS "measurements_legacy_step_consolidation_idx"
|
|
ON "measurements" ("user_id", "measured_at")
|
|
WHERE "type" = 'ACTIVITY_STEPS'
|
|
AND "deleted_at" IS NULL;
|