feat(issues): the honest processing-issues ledger — row-less import failures, self-healing resolution, family lens (faceted plan Phase 11)
processing_issues only recorded cross-library move rejections; files that failed to import vanished into an error counter and stdout. The ledger now records every failure class and heals itself: Schema (in place, pre-release boundary): - media_item_id NULLABLE + file_path TEXT (deliberately unbounded — an over-long path is itself a failure mode; a VARCHAR(500) ledger column died on the exact 22001 it existed to report — caught by the new test). Row-less failures key on (library, file_path); item-backed on (item, type). Widened dedup = COALESCE-expression unique index; the old table UNIQUE stays (NULLs pairwise-distinct for row-less). - Conflict-target upsert: repeat failures UPDATE the same row and REOPEN resolved ones — never duplicates. Wirings: - CreateMediaItem failure (single-file + multifile createAudioBookItem) → row-less import_failed (error). - Extraction hard-fail with fallback import → item-backed metadata_extraction_failed (warning). - Change-path re-extraction failure (the ev/sidecar guard) → item-backed metadata_extraction_failed; LogProcessingIssue keeps its signature, a row-less helper joins it. Auto-resolution: - Successful import → ResolveOpenProcessingIssuesForPath (library, file_path). - Successful (re)extraction → ResolveOpenProcessingIssuesForItem (single-file change path, multifile editorial apply). - Unchanged-skip scans do NOT resolve: extraction never re-ran, so the degraded metadata is still degraded — the page heals exactly when the book does. Family lens on ALL issues surfaces (list, stats, resolve, delete, SSR page): explicit out-of-set library id → 403, never silent. This tightens one pre-lens behavior — a nonexistent library id returned 200-empty, now 403 (pinned, changelog entry in docs/contract_pins.md). List is LEFT-JOINed so row-less rows appear (media_item_id "", title falls back to the path). Tests: full lifecycle state machine through real scans (fail → appears, repeat → no dups, success-at-path → resolved, LEFT-JOIN list shape); family lens 403s with a fresh non-shared admin; all 7 pre-existing issue suites green (two expectations widened to the lens, changelogged); adjacent suites (CrossLibraryMove, Audiobook, Calibre, ExtractorVersion, SchemaIdempotency) green; unit suites green.
This commit is contained in:
1 parent
19b9c7c9b8
commit
9b5defcb31
50 files changed
+1244
-681
No files matched your search
@@ -367,3 +367,31 @@ cover_image_path, has_conflict, format_group, badge`.
|
||||
- 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).
|
||||
|
||||
## 2026-10-20 — Scanner Phase 11: the processing-issues ledger
|
||||
- `processing_issues.media_item_id` is now NULLABLE and the table gains
|
||||
`file_path` (TEXT, deliberately unbounded — an over-long path is
|
||||
itself a failure mode the ledger must survive): ROW-LESS import
|
||||
failures (no media_items row exists) key on (library, file_path);
|
||||
item-backed rows keep (item, type). The widened dedup is the
|
||||
COALESCE-expression unique index idx_processing_issues_dedup; the old
|
||||
table-level UNIQUE stays (row-less rows have NULL items, pairwise
|
||||
distinct under unique constraints).
|
||||
- `GET /api/libraries/:id/issues/list` — the media_items join is now
|
||||
LEFT: row-less issues APPEAR (they were unrepresentable before).
|
||||
Response shape unchanged for item-backed rows; row-less rows carry
|
||||
`media_item_id: ""` and a `title` fallen back to the file path.
|
||||
- FAMILY LENS now applies to ALL issues endpoints (list, stats, resolve,
|
||||
delete) and the SSR page — they leak media metadata. An explicit
|
||||
library id outside the requester's visible set is a **403** (this
|
||||
tightens one pre-lens behavior: a nonexistent library id used to
|
||||
return 200-empty; it is trivially out-of-set → 403 now, pinned).
|
||||
- NEW scanner wirings: CreateMediaItem failure → row-less
|
||||
`import_failed` (error); extraction hard-fail with fallback import →
|
||||
item-backed `metadata_extraction_failed` (warning); change-path
|
||||
re-extraction failure → item-backed `metadata_extraction_failed`.
|
||||
- Auto-resolution: a successful import resolves row-less issues by
|
||||
(library, file_path); a successful (re)extraction resolves the item's
|
||||
open issues. Unchanged-skip scans do NOT resolve (extraction never
|
||||
re-ran — the degraded metadata is still degraded). A repeat failure
|
||||
reopens a resolved row (upsert sets resolved=false).
|
||||
Reference in new issue
Block a user