feat(dates): backfill drain converts mixed-convention rows to true instants (#118)

Per-tick drain (backfill_utc_dates) at the existing date-drain seam,
inside the per-library online gate. Selects date_utc IS NULL AND
date_taken IS NOT NULL (new partial index idx_image_exif_utc_backfill),
re-runs resolve_dates_batch with empty priors (one exiftool subprocess
per batch, same call shape as the #117 audit), and writes only the
new-contract triple; the legacy pair stays frozen. Capped by
DATE_BACKFILL_MAX_PER_TICK; missing-file rows are paged past without
spending the cap. Legacy manual overrides convert via
manual_date_resolution rather than being re-resolved from the file.

Day-boundary invalidation deletes the day-span precomputed reels
covering a re-dated row's old/new display-zone month-day so the nightly
pre-gen regenerates them. Progress: imageserver_date_backfill_remaining
gauge + date_backfill_remaining on GET /libraries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Cameron CordesandClaude Opus 5.5 committed 2026-09-26 09:24:14 -04:00
1 parent 3ac011abd7
commit 1fad08dea3
11 files changed
+1185 -4

No files matched your search

+20
View File
@@ -437,6 +437,26 @@ a stronger tool comes online (exiftool install, new filename regex),
re-resolve out-of-band rather than re-introducing the steady-state
eligibility.
**True-instant drain (`backfill_utc_dates`, ticket #118).** Runs right
after `backfill_missing_date_taken` inside the per-library online gate,
sharing its `DATE_BACKFILL_MAX_PER_TICK` cap. Converts legacy
mixed-convention rows (`date_utc IS NULL AND date_taken IS NOT NULL`,
partial index `idx_image_exif_utc_backfill`) by re-running
`resolve_dates_batch` with empty priors (one exiftool subprocess per
batch) and writing **only** the new-contract triple — the legacy pair
stays frozen. Legacy `manual` rows convert via
`camera_tz::manual_date_resolution` instead of being re-resolved from
the file. Missing-file rows are paged past without spending the cap;
EXIF/exiftool-legacy rows wait when exiftool is absent (they'd otherwise
fall to fs_time). When a converted row's display-zone day differs from
the day its legacy value rendered on, the `day`-span `precomputed_reels`
rows covering either month-day (this library + `all`) are deleted and
unlinked; the nightly pre-gen regenerates. Daily conversation summaries
are SMS-derived and unaffected. Progress: Prometheus
`imageserver_date_backfill_remaining` (per tick) and
`date_backfill_remaining` per library on `GET /libraries` (live count of
`date_utc IS NULL`).
`/memories` is a single SQL query against this column
(`get_memories_in_window` in `src/database/mod.rs`), using
`strftime('%m-%d' | '%W' | '%m', date_taken, 'unixepoch', tz)` for