ancestors() cannot give the order it was documented to give #161
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?
ItemReader::ancestorspromised nearest first.ANCESTORSincrates/ephyra-db/src/items/statements.rsrecovers it from the shape of thetable:
Against a real upstream database that does not order the chain. Upstream files
a
CollectionFolderunder theUserRootFolderalone and the directory itpoints at under the
AggregateFolderalone, so for anything inside a libraryboth carry exactly one ancestor of their own and the tie falls to whichever id
sorts lower. Run over
reference/snapshots/default, for a film:The directory comes first here by hash and not by depth. The comments now say
that instead of promising an order (
6684877), which is the honest half; thisis the other half.
Why nothing is broken today
Every caller names the type it wants rather than taking the first:
latest.rs::nearest_ancestorfilters forMusicAlbumorPhotoAlbum,collections.rs::library_foldersfilters for a collection folder, andviews.rsuses.any. The next order-sensitive caller is the one thatinherits the problem.
Where to start
The chain's order is in the parent pointers, not in
AncestorIds— upstreamwalks
GetParents()for it and denormalizes the set without the order. So thequestion is whether a caller that genuinely needs the chain gets a walk of
ParentId(one lookup per level, on a path that is a single query today), orwhether naming the type is the contract and
ancestorsshould return a setrather than a sequence and say so in its own signature.
Filed rather than built because no caller wants an order yet, and picking the
walk before one does buys a per-level query nobody reads.
House rules
Tests run under
cargo nextest; upstream's source is the checkout inupstream/at the pin. The reference on:8096is read-only.Fixed in
8db3232, and the answer turned out to be both halves rather than achoice between them: the two questions are different questions.
Measured against
reference/snapshots/default, for a film:The
CollectionFolderis not in the chain at all — a library is not above thedirectory on disk, it covers it. So
AncestorIdsis two structures in onetable and there is no nearest in it to recover; the heuristic was answering by
whichever id sorted lower.
ancestorsstays what the membership callers want and now says it is a set,ordered by id so two reads of one database agree.
parent_chainis new: a recursive walk ofParentId, nearest first, in onequery. That is what upstream's
GetParents()walks, andFindParent<T>andPhoto.AlbumEntityboth take the first match from it.latest.rs::container_ofasks the second one now. Checked that the album isstill reached: a track's chain on the reference is
MusicAlbum → MusicArtist → Folder → root, so the album is at depth 0 rather than found by luck — and thenested-photo-album case the set could never answer now has an answer.
what_an_item_is_filed_under_comes_back_as_a_setandthe_parents_come_back_nearest_firstreplaceancestors_come_back_nearest_first,which asserted the promise this issue is about. Both fail if the ordering is
reversed.
A review of the fix caught that
PARENT_CHAINhad no bound, fixed in4fb618d.UNION ALLcarries an incrementing depth, so nothing dedups the recursionaway: a row that is its own parent, or a pair that name each other, is a walk
that never comes back — a pinned pool connection and growing memory, where
upstream's lazy
GetParents()enumerable would return on the first match. Theforeign key on the parent column says the row exists, not that it is above this
one, so neither shape is refused by the schema.
Bounded at 64 climbs, with
a_parent_that_points_at_itself_does_not_climb_foreverover a fixture row pointed at itself.
The route at
/Items/{id}/Ancestorswalks the same column in Rust(
detail.rs::ancestors,while let Some(id) = next) and is unbounded for thesame reason. It predates this work and is left alone here.