diff options
Diffstat (limited to 'docs/mediacenter.md')
| -rw-r--r-- | docs/mediacenter.md | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/docs/mediacenter.md b/docs/mediacenter.md index dbdf85c..d714366 100644 --- a/docs/mediacenter.md +++ b/docs/mediacenter.md @@ -904,6 +904,49 @@ only when there is nothing else, and the lowest *number* rather than the first entry so it does not quietly depend on `buildSeasons` keeping its sort. `test_video_default_season.py` — no input it takes can carry a thumbnail. +### 10.6 The same film twice in the cross-group Search view (2026-09-02) + +An operator hosting two groups gave both the *same* video directory — which is +the point of having two groups: different people are invited to different +libraries, and one library may be in several of them. **Search files** then +showed every film as two poster cards and every episode twice in the season +list, one copy badged per group. Flat list too. + +Not a Videos bug. Inside a group it cannot happen: `GroupIndex` is keyed by +blake3, so the same bytes at two paths are already one entry. `search-page.js` +concatenates *N* independently keyed indexes into one list, and that is where +the duplication is born. + +`source-merge.js` folds entries on the content hash and resolves **one source +per unit** — a film, a whole show — rather than per file: a season split across +two nodes would open two connections and two metadata lookups for one show. A +group hosted by the reader's own node wins (read from `handshake_ack`'s +`is_node_admin`, which the node computes from its own record of who it belongs +to, never a hub claim); failing that the pick is `hash(unitKey + userId)`, +stable for one reader across renders and reloads — a source that changed +mid-stream would tear down the connection under a film that is playing — and +spread across readers. + +The units come from **`groupVideoEntries` itself**, called on the un-merged +list purely to learn them, never a second copy of its keys in the Search page. +A copy would keep agreeing until one of them changed, and the symptom would be +a show whose episodes stream from two different nodes. + +Two consequences worth knowing: + +- **An operator's "Fix match" and "Rematch" go to the chosen source's node.** + On the operator's own libraries that is their node, which is what they mean. + On a merged entry they do not host, the override lands on whichever group was + picked — and the other source keeps its own match. +- **`PosterGrid.mergedShows` still merges two differently-parsed titles once + both resolve to the same TMDB id.** Those were two units when the source was + picked, so a merged card can hold two sources. Left alone deliberately: + re-picking under a card the reader is looking at is worse than a mixed one. + +Full design, the adversary this names, and what must not change: +`docs/refactoring-search.md`. `test_search_source_merge.py` holds the rules, +`test_search_media_merge.py` holds this symptom end to end. + ## 11. Acceptance before shipping 1. Re-run the §3 validation (real TMDB calls, same corpus, same script |