/Years counts the folders its walk passed through, and answers an unsorted page in a different order #89
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?
/Yearswas closed for ordering in #86. Two differences remain, both measured, neither an artefact.TotalRecordCountcounts different thingsGetYearstakes its total fromFolder.GetRecursiveChildren(user, query, out totalCount), which isAddChildrenFromCollection:childCount = realChildren.Lengthat each level, plus the recursive sum over every visible sub-folder. Folders are counted, and there is no de-duplication — theresultdictionary de-dups the items, the count does not.For the snapshot that is the user root's 4 children + movies 3 + music 1 + shows 1 + Playlists 0 + artist 1 + album 2 + series 2 + seasons 4 = 18, confirmed live per folder. Ours reports a flat recursive row count, which is 17.
Reproducing it means modelling upstream's walk, not changing a line.
The unsorted page is in a different order
Upstream's is the depth-first order
AddChildrenbuilds over the user root (movies, shows, music); ours is whatever the SQL returns.SortBy=Defaultnow answers the same page as no sort on each server — that part matches upstream, where no comparer declaresItemSortBy.DefaultsoSortleaves the walk order alone — but the two servers still disagree on what that walk order is.portable.jsonnever sees either, because it always sendsSortBy=SortName.Not this, for the record
The 100 remaining anchor differences on this route (50
Items[n].Id, 50Items[n].UserData.ItemId) are a fixture artefact and not a bug: the anchor carries two rows per year, one written by an earlier run whose metadata directory sat outside its program data directory. EveryNameagrees positionally and both servers answer the same set of years, so the page is the right page. The ids agree on a correctly-arranged snapshot pair.Investigated and not fixed, with the reason measured rather than asserted. Both halves need the same thing, and it is not a query change.
Why both halves are the same problem
Upstream's total comes from
Folder.GetRecursiveChildren, and its unsorted order is that same walk's order. So reproducing either means reproducing the walk. Three things make that infrastructure rather than SQL:1. A collection folder's children are linked, not parented. Walking the anchor's
BaseItemsfrom the user root throughParentIdreaches 3 rows — the three collection folders — and stops. Every one of the 21.9k library items hangs off a physical folder that the collection folder reaches throughLinkedChildren, which this port does not model at all. (That same gap was confirmed independently while closing #90: nothing here readsLinkedChildren, which is why upstream'sdto.ChildCount ??= folder.LinkedChildren.Lengthstep is unreachable for us.)2. The walk is type-dependent.
MusicAlbumoverridesGetEligibleChildrenForRecursiveChildrento return itsTracksrather than its children. Matching the count means porting those overrides, not just descending a parent column.3. The count is not a count of anything the database can be asked for.
AddChildrenFromCollectionsumsrealChildren.Lengthat every level with no de-duplication — theresultdictionary de-dups the items, the count does not. It counts folders it passed through, and it counts a row twice where the walk reaches it twice.That last point is why no single rule explains both fixtures: on
reference/snapshots/defaultupstream is higher than ours (18 against 17), and on the anchor it is lower (21,829 against 21,895). A rule fitted to one gets the other backwards.What it would cost
Measured on the anchor pair,
GET /Years?Limit=50&SortBy=SortName, warm:Upstream is ~3× slower on this route, and the walk is what it is spending the time on. Reproducing the number faithfully means adopting that cost — visiting every item in the library per request where we currently answer with one aggregate query — plus modelling
LinkedChildrenand the per-type child overrides to get there.What is not wrong
The remaining 100
/Yearsdifferences on the anchor areItems[n].IdandItems[n].UserData.ItemIdonly. EveryNameagrees positionally and both servers answer the same set of years, so the page is the right page; those ids are an artefact of that fixture carrying two rows per year from an earlier run whose metadata directory sat outside its program data directory. The ordering that #86 closed is still closed, andSortBy=Defaultanswers the same page as no sort on both servers.Recommendation
Leave it. The visible symptom is a total that is out by 0.3% on a 21k library and a page order that only a client sorting by nothing at all would see, and the fix costs a walk of the whole library per request. Worth reopening if
LinkedChildrenis ever modelled for another reason — at that point both halves become reachable together.