feat(scanner): extractor-version (ev) mechanism — parser fixes reach old rows without a force rescan (faceted plan Phase 10)
Parser fixes (7e4c97f6, genre model v2) never reached rows ingested
under an older parser: the sidecar never changed, so every fingerprint
said 'unchanged'. The manifest JSONB now carries the reserved 'ev'
stamp — the parser version that produced the item's row.
Semantics (all pinned by tests):
- ABSENT ev decodes as 1 ('v1-or-unknown'); stamping is truthful-only:
create paths + post-extraction stores stamp the setting's current
value; deploy-day backfill and the extract-failure guard stay UNSET
(a row never claims a version its data can't prove — a mid-backfill
bump self-heals next poll); repoint reconciliation preserves the
stored ev (stat-only refresh re-extracted nothing).
- NEW setting scan_extractor_version (seeded + registry + getter,
int default 1, category scanner): a manifest whose ev != the setting
re-extracts through the SAME change path (full extraction →
updateMediaItemWithMetadata → fresh stamped manifest). Sidecar-less
books get an entries-less manifest as their ev home (create: stamped;
first-sighting: unset).
- Catch-up bounded: evReextractBudgetPerScan=100, atomic (watcher pass
can overlap a poll scan), reset per ScanFolders — amortized +
resumable across polls; no force rescan, no flood.
- Multifile books included: the ev gate rides multifileSidecarChanged's
shared ladder; ev-driven manifestChanged drives the editorial apply
+ stamped re-store.
Settings API: the unified GET/PUT /api/system/settings now lists the
key (registry-driven, auto-surfaces in the admin UI). Test harness:
the registry is now Loaded + wired into the SystemSettingsHandler
(main.go parity) — settings writes through the API were 503s before.
Verified: unit (ev normalization, budget CAS, GetExtractorVersion
cache paths, registry clamping); integration state machine —
create-stamp ev=1 → equality skips (corruption probe persists) →
wiped scan-state backfills UNSET without re-extract → bump re-extracts
ONCE (sidecar value restored, ev=2) → stable (second corruption
persists); multifile twin green; adjacent suites (Audiobook, Calibre,
CrossLibraryMove, SchemaIdempotency) green; live app restart re-scans
1198 files with 0 changed (deploy-day rule), setting listed at
/api/system/settings.
This commit is contained in:
1 parent
43987262a6
commit
91b0c45dd4
10 files changed
+486
-10
No files matched your search
@@ -342,3 +342,28 @@ cover_image_path, has_conflict, format_group, badge`.
|
||||
- The Phase-7 facet-panel partial stays removed; the all-facets JSON
|
||||
endpoint and its two shapes are unchanged (they serve flat params —
|
||||
the builder's UI does not use them).
|
||||
|
||||
## 2026-10-20 — Scanner Phase 10: extractor version (ev) mechanism
|
||||
- `media_scan_state.manifest` JSONB gains the reserved `ev` key:
|
||||
the parser version that produced the item's CURRENT row. ABSENT
|
||||
means "v1-or-unknown" — decode normalizes it to 1.
|
||||
- NEW setting `scan_extractor_version` (int, default 1, min 1,
|
||||
category scanner): the unified `GET/PUT /api/system/settings` list
|
||||
now includes this key (additive; the list was not a pinned closed
|
||||
set). Writes stay settings-API-only — direct SQL leaves the registry
|
||||
cache stale (known gotcha).
|
||||
- Scanner behavior: a stored manifest whose ev ≠ the setting is
|
||||
treated as CHANGED → full re-extract + the fresh manifest stamps
|
||||
the new ev. Stamping is TRUTHFUL-ONLY: create paths and
|
||||
post-extraction stores stamp; deploy-day BACKFILL and the
|
||||
extract-failure guard store UNSET (the row never claims a version
|
||||
its data can't prove — a mid-backfill bump self-heals next poll).
|
||||
Repoint reconciliation preserves the stored ev (stat-only refresh,
|
||||
nothing re-extracted).
|
||||
- Catch-up is BOUNDED per scan pass (`evReextractBudgetPerScan = 100`,
|
||||
atomic, reset at each ScanFolders): resumable across polls, no
|
||||
force rescan, no flood. Budget exhaustion leaves ev stale → later
|
||||
polls resume.
|
||||
- Deploy-day rule (unchanged, re-verified live): manifests without ev
|
||||
ride v1; at default setting 1 the first post-release scan re-extracts
|
||||
NOTHING (0 changed on 1198 files).
|
||||
Reference in new issue
Block a user