fix(library): seed a default quality profile and reject invalid profile ids; profile-less adds were silently never searched#760
Open
t3chnaztea wants to merge 1 commit into
Conversation
…le ids Monitored audiobooks silently never grabbed on fresh installs. Three compounding gaps: no default quality profile was ever seeded, so GetDefaultAsync returned null; the add path then persisted the audiobook with QualityProfileId = null anyway (and accepted a caller-supplied id without checking it exists); and the automatic-search query filters QualityProfileId != null, so those books were never searched and nothing surfaced the problem. - Seed a permissive "Any Quality" default profile at startup when the QualityProfiles table is empty, via the existing StartupDbNormalizer hosted service (always registered, even when other hosted services are disabled). Idempotent: only seeds when no profile exists. Normalization and seeding are now guarded independently so a normalization failure no longer skips the seed. Shape built by QualityProfile.CreateDefault(). - Reject the add when a supplied QualityProfileId does not exist, or when no profile is supplied and no default can be resolved, instead of persisting a null-profile row. Surfaced as a 400 (BadRequest) through LibraryAddWorkflow; the primary LibraryAddService path reports this via a new LibraryAddOperationResult.Rejected flag, validated before any persistence-side work. The automatic-search query (QualityProfileId != null) is unchanged: with seeding + rejection the null-profile state can no longer arise for new adds. Existing rows already written with a null quality profile still need manual profile assignment (or a follow-up normalizer) before they will be searched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
Three compounding gaps meant a monitored book on a fresh install could silently never grab anything, with no warning anywhere:
QualityProfileRepository.GetDefaultAsyncreturns null on a fresh database (there is no seed data repo-wide).LibraryAddService) and the workflow fallback (LibraryAddWorkflow) logged a warning and persisted the audiobook withQualityProfileId = null; a caller-supplied profile id was assigned without checking it exists.QualityProfileId != null, so those books are never searched — and nothing ever surfaces that.The fix
StartupDbNormalizer(the existing startup-normalization hosted service) now seeds one permissive "Any Quality" default profile when theQualityProfilestable is empty. Idempotent (AnyAsyncgate); the shape matches what the UI creates (built on the required-qualities set thatEnsureProfileHasRequiredQualitiesAsyncback-fills anyway). The normalizer's JSON-column pass and the seed pass are now independently guarded, so a normalization error can't swallow the seed.LibraryAddService(and the workflow fallback, which had the identical bug), a supplied profile id that doesn't exist rejects the add with a 400 and a clear message, before any side effects (image move/persistence); no supplied id resolves the default, and if somehow none exists the add is rejected instead of persisting a book that will never be searched.Out of scope, flagged for maintainers: rows already persisted with
QualityProfileId = nullon existing installs still need manual assignment (or a follow-up normalizer) before automatic search will see them. The search query itself is deliberately untouched.Tests (7 new)
QualityProfileSeedTests: empty table seeds exactly one default; running twice stays at one; non-empty table seeds nothing.StartupDbNormalizerSeedTests: fresh DB via the hosted service seeds exactly one; idempotent on re-run.LibraryController_QualityProfileValidationTests: bogus profile id → 400, nothing persisted; no profile id → default assigned, persisted non-null.Full suite green: 1196 passed / 0 failed;
dotnet format --verify-no-changesclean.🤖 Generated with Claude Code