fix(monitoring): keep every series membership and its identifier when a monitored author or series adds a book - #961
Open
m4bard wants to merge 2 commits into
Conversation
…itored author or series adds a book Both monitoring mappers took only the first entry of the catalog's series list and copied its name and position into the legacy Series/SeriesNumber fields. They never set SeriesMemberships, so AudibleBookMetadata.ToAudiobook fell back to building a single membership out of those two legacy strings, with SeriesAsin null. Every series past the first was dropped, and the identifier the catalog had already supplied on each entry was thrown away. What that looks like in a library: books that arrived through a monitored author or a monitored series carry no series identifier at all, and a book belonging to more than one series shows only one of them. Since the series identifier is what lets two spellings of the same series collapse onto one tile, a localised name and its English original stay as separate tiles with nothing to join them on. Both mappers now build memberships from the whole catalog list through the same MetadataConverters.BuildSeriesMemberships the search add path uses, so a book added by monitoring gets the same shape as one added by hand. The legacy Series/SeriesNumber columns are still populated, now read off the primary membership so the two can't disagree. This only changes what is written when a book is added. Rows already in the library keep the memberships they were given; a metadata refresh re-reads them from the provider and repairs them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ntifier The frontend has been sending seriesAsin on the add payload for a while, and the type it builds from declares the field, but AudibleBookMetadata had no such property, so the value never bound to anything. It was dropped at the model boundary and no one could see where. The property is added beside Series and SeriesNumber and passed as the legacy series ASIN wherever those two are already passed. Every one of those four sites passed the pair and stopped there: ToAudiobook, the add workflow, the metadata rescan patch and the path preview. All four pass the identifier now, so a payload that describes its series with the three legacy fields and no membership list lands with an identifier on the single membership built out of them, instead of a name-and-number pair nothing can be matched on later, and it does so whichever door it came through. The rescan patch still rewrites an audiobook's series only when the incoming record carries memberships, a series name or a series number, and that guard is deliberately not widened to a payload carrying an ASIN alone. The helper's legacy fallback needs a name to build a membership from, so an ASIN by itself would clear the memberships the book already has rather than improve them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
m4bard
force-pushed
the
fix/monitoring-series-memberships
branch
from
September 15, 2026 18:35
1fabd72 to
321ff40
Compare
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.
Fixes #962.
Two commits, backend only.
The first makes the author and series monitoring jobs keep what the catalog gives them. Both mappers took
book.Series?.FirstOrDefault()and wrote its name and position into the legacySeriesandSeriesNumberfields, never settingSeriesMemberships, so every book that arrived through monitoring got one membership built from the legacy fallback with no identifier, and any further series was discarded. They now build the full list through the sameMetadataConverters.BuildSeriesMembershipsthe search conversion uses, and the legacy fields are read off the primary membership after normalization so the two cannot disagree.BuildSeriesMembershipsgoes from private to internal for that; same assembly.The second gives
AudibleBookMetadataaSeriesAsinproperty and passes it as the legacy identifier at the four places that already passSeriesandSeriesNumber(ToAudiobook, the add workflow, the rescan patch, the naming preview). The frontend has declared and sentseriesAsinall along; it never bound. A payload that only carries the legacy fields can now keep its identifier. The rescan guard is deliberately not widened to a payload carrying only an identifier, because the helper's fallback needs a series name and an identifier alone would wipe the book's existing memberships.Tests: six on the mappers (two series with identifiers kept in order with the first primary, legacy fields equal to the primary, no series, blank identifier), one on the metadata model, and the existing suites unchanged.
dotnet format --verify-no-changesclean.Validated on a running install, but for the wizard add path only. Importing a fixture book through the library import wizard produced one new membership with the series identifier from the catalogue lookup on it, and its name and position matched the legacy fields. The control is the rest of the membership table: a couple of thousand pre-existing rows, none of them with an identifier, none of them changed. On the previous build the same import wrote a null identifier. The monitoring mapper half is covered by tests only, since the author sync cannot be triggered from outside and runs on a 24 hour interval. The repair of existing rows I deliberately did not run; it waits on a separate bulk refresh.
Related: #847 does the same for the import wizard and the unmatched-files add, and #768 for the Audnexus lookup and converter. With all three, every add path keeps identifiers and memberships; existing rows need a metadata rescan to pick them up.
Disclosure: drafted with Claude Code at my direction; I read the cited code at the stated commit and reviewed this before posting.