/Studios search orders two studios differently from upstream #122
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Measured on the live pair during #91's review:
Both servers find the same three; they disagree about which of the two non-prefix matches comes first. This is distinct from the studio-picture difference
crates/jellyfin-harness/README.mdalready names.The likely root is the search ranking rather than the listing: a term the name starts with outranks one it merely contains, and among the ones that merely contain it upstream has a tiebreak this port does not reproduce.
Warner Bros.containsBrat a word start;Shaw Brothersdoes too. So the tiebreak is something else — read it rather than guess.Related and already settled once: closed issue #88 was "the search candidate cut runs over the whole narrowing, and there is no fallback when the ranking matches nothing", and #49 was "search hints come back in a different order". This is the same family and the fix probably belongs beside them.
Where to start
The by-name listing and its search ranking,
crates/jellyfin-app/src/scan/by_name.rsand the discover routes incrates/jellyfin-http/src/routes/discover.rs. Upstream's ranking is in its search engine rather than in the controller.How to know it is done
The measurement agrees, and a scenario carries a
searchTermover a by-name listing with more than one non-prefix match — the shape that finds this.House rules
Tests run under
cargo nextest; upstream's source is the checkout inupstream/at the pin (
v12.0-rc5,6d501ba4); generated files are regenerated ratherthan edited; comments say what the code does, not how it got there. The
reference pair is
cargo xtask reference up, a run iscargo run -p jellyfin-harness -- replay --upstream URL --ours URL --scenario FILE --out DIR,and
crates/jellyfin-harness/README.mdsays what a diff means. A server startedoff current
mainbinds UDP 7359 for discovery — set[discovery] enabled = falsein a scratch config if another one is already running.
Done, on
main.The ranking tiers were right; the tiebreak was not.
BaseItemRepository.QueryBuilding.cs:366adds the trailingSortNamekey onlyif (!hasSearch), so a search suppresses it and ties fall out in the orderWHERE Id IN (...)yields — primary-key order. We were sorting ties by name.Confirmed on a listing with four tied rows:
/Genres?searchTerm=rgivesDrama, Thriller, Adventure, Mysteryon both — id order, conspicuously not alphabetical — whilesearchTerm=dgivesDrama, Adventure, prefix outranking contains.One thing left deliberately:
by_relevanceranks on the folded name where upstream'sMapSearchRelevanceOrderalso matchesOriginalTitle. A by-name row stands for an interned value and carries none, so both halves of every tier consulting it are unreachable — and the code now says so rather than leaving it silent.The batch this closed in
Seven issues went out together because they looked like one defect class. They turned out to be three roots:
/Items'Paramshad been grown one client at a time instead of held against upstream's controller signature, and/UserItems/Resumeshared it.sortBy=Namemaps toCleanNameupstream, notSortName, and a by-name search orders by relevance with no sort-name tiebreak, so ties fall out in id order.PremiereDatecoalesces withProductionYearwhere ours read the bare column.A reviewer re-derived the parameter audit mechanically — extracting every
[FromQuery]name fromGetItemsand doing set arithmetic against what we bind — and got nothing bound that upstream does not take and nothing in the register that is not an upstream parameter. This class is closed rather than narrowed, which matters because it had been found three times.Verified on a restored pair:
browsing34 → 0,items33 requests at 0,clients56 → 3,portable115 → 6.JELLYFIN_RS_REQUIRE_FIXTURES=1 cargo nextest run --workspace: 2228 passed, 0 skipped. Clippy clean. No ignore-list entry was added or touched.Two things the review caught that the batch had not
Five of the ten new scenario entries could not fail. The
defaultsnapshot has no genres, studios or tags, so fiveitems.jsonentries compared two empty pages — reverting the whole fix would still have replayed clean. They moved intoediting.json, after the save that gives one film a genre, a tag, a certificate and a studio and then takes them away, so each selects one row out of nineteen. That is the fifth time this session the same failure has turned up in a different layer, after M5's vacuous scenarios, M8'sbundle.json, #111's all-refusalsvisibility.jsonand #137's silently-skipping tests.Reading the reference can write to it.
Studios=,Artists=andAlbums=resolve through upstream'sGetStudio/GetArtist, which callCreateItemByName— so a read files aBaseItemsrow. That is how a strayBrandywine Productionsgot into the shared fixture mid-session and madeportable.jsondisagree by 149.Genres,TagsandOfficialRatingsnarrow throughItemValuesand are safe. Both halves are now written intocrates/jellyfin-harness/README.md.