Skip to content

Fix: approved imports silently delete higher-quality files of the same book - #92

Open
sebclark wants to merge 1 commit into
Chaptarr:developfrom
sebclark:fix-import-quality-downgrade-guard
Open

Fix: approved imports silently delete higher-quality files of the same book#92
sebclark wants to merge 1 commit into
Chaptarr:developfrom
sebclark:fix-import-quality-downgrade-guard

Conversation

@sebclark

Copy link
Copy Markdown
Contributor

The bug

Every quality protection lives in the grab-side decision engine (UpgradeDiskSpecification, QueueSpecification, HistorySpecification) - they stop worse releases being grabbed. The import side has no quality comparison at all: once a file is matched and approved for import (a completed download matching a different edition, a manual import, a retry pass), UpgradeMediaFileService.UpgradeBookFile unconditionally deletes every existing file of the book before moving the new one in.

The edition-switch path makes this destructive in practice: an incoming MP3 that matches a different edition of a book than the one whose M4B you hold sails past the grab-side specs (they compared within the grabbed edition), reaches UpgradeBookFile, and the M4B is deleted with reason "Upgrade". With no recycle bin configured (the default), the file is gone permanently.

I verified the behaviour on pristine develop with a probe test - existing M4B-quality file on the book, incoming MP3 - and it deletes the M4B without any comparison. On my install a batch of MP3-edition downloads destroyed a run of M4B files this way (recovered most from still-seeding source data; the rest were permanent losses).

The fix

A last-line guard in UpgradeBookFile: before deleting existing files, compare each against the incoming file using QualityModelComparer over the author's per-media quality profile. If any existing file outranks the incoming one, throw instead of deleting - the import surfaces as a visible failure rather than a silent downgrade. Genuine upgrades (MP3 -> M4B) and same-rank replacements behave exactly as before; grab-side selection logic is untouched.

A dedicated decision-layer fix (comparing quality across editions before approving the switch) might be the nicer long-term shape - happy to rework in that direction if you prefer; this guard is the minimal stop-the-data-loss version and is running in production on my install.

Tests

Two new tests in UpgradeMediaFileServiceFixture: refuse-downgrade (M4B on disk, MP3 incoming -> throws, nothing deleted) and upgrade-still-works (MP3 on disk, M4B incoming -> replaced as before). A literal fails-first run isn't possible for the refusal test since it needs the widened constructor (new IQualityProfileService dependency) - the pristine destructive behaviour was verified with a separate probe test instead, as described above. Full Core.Test suite green: 2854/2854.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant