Parent image fields disagree with upstream in both directions #70

Closed
opened 2026-08-04 15:18:29 +02:00 by Claude · 1 comment
Collaborator

Parent image fields are sent where upstream sends none, and missed where it
sends them.

/Items?Recursive=true&SortBy=SortName — 21,895 items, both servers on one
database — comes back 894,842 bytes longer than upstream's. Counted per
field over that response:

field items differing
ParentBackdropImageTags / ParentBackdropItemId 3,297
ParentLogoImageTag / ParentLogoItemId 3,033
AlbumPrimaryImageTag 2,722 — upstream sends it, we do not
ImageBlurHashes 5,604

The first two are the opposite of the third: this server walks its ancestry and
attaches a parent's backdrop and logo where upstream attaches none, while
upstream names a track's album image and this server does not.

DtoService.AttachBasicFields decides each of these separately — which parent
is asked, and which image types are borrowed from it — rather than by one
inheritance rule. That per-field detail is what to port.

Measured after #63 and #65, both of which moved these numbers down; this is what
is left. ImageBlurHashes is downstream of whichever tag is wrong, so it should
follow the others rather than needing its own fix.

Body length is not the target — per-field differing-item counts are. The byte
figure is quoted only because it is what makes this visible in the harness,
where the response is compared on length alone.

Parent image fields are sent where upstream sends none, and missed where it sends them. `/Items?Recursive=true&SortBy=SortName` — 21,895 items, both servers on one database — comes back **894,842 bytes longer** than upstream's. Counted per field over that response: | field | items differing | |---|---| | `ParentBackdropImageTags` / `ParentBackdropItemId` | 3,297 | | `ParentLogoImageTag` / `ParentLogoItemId` | 3,033 | | `AlbumPrimaryImageTag` | 2,722 — upstream sends it, we do not | | `ImageBlurHashes` | 5,604 | The first two are the opposite of the third: this server walks its ancestry and attaches a parent's backdrop and logo where upstream attaches none, while upstream names a track's album image and this server does not. `DtoService.AttachBasicFields` decides each of these separately — which parent is asked, and which image types are borrowed from it — rather than by one inheritance rule. That per-field detail is what to port. Measured after #63 and #65, both of which moved these numbers down; this is what is left. `ImageBlurHashes` is downstream of whichever tag is wrong, so it should follow the others rather than needing its own fix. Body length is not the target — per-field differing-item counts are. The byte figure is quoted only because it is what makes this visible in the harness, where the response is compared on length alone.
Author
Collaborator

Fixed, all four fields to zero, from one fact about upstream.

GetImageDisplayParent (DtoService.cs:1522) sends a MusicAlbum to the
artist it names, not to the folder above it — and that artist is looked up
in a batch (LinkedChildrenService.FindArtists) whose query does not include
the images navigation. So an album that names an artist gets an image-less row,
borrows nothing, and the walk ends there, because MusicArtist does not inherit
images. Only an album naming an artist no row answers falls back to its real
ancestor.

That single fact accounts for all 6,330 excess ParentBackdrop*/ParentLogo*
items.

Beside it: AddInheritedImages returns early unless the item itself supports
inherited images (true only for audio, albums, videos, seasons and folders —
BaseItem's default is false), AlbumPrimaryImageTag comes from the track's
own album entity, and a blurhash is filed only when the column is non-empty.

field before after
ImageBlurHashes 5,572 0
ParentBackdropImageTags / ItemId 3,297 0
ParentLogoImageTag / ItemId 3,033 0
AlbumPrimaryImageTag 2,722 0

The reading was validated by simulating upstream's whole walk against the
database: it reproduces ParentLogoItemId, ParentThumbItemId and
ParentBackdropItemId for all 21,895 items with 0 mismatches, and ablating
either the album-to-artist redirect or the image-less-batch rule reproduces the
reported counts exactly.

One regression this caused and fixed in the same branch: search hints derived
their backdrop from the borrowed fields, which the tighter walk emptied for 7
tracks. Upstream's hint reads the raw parent chain with no inheritance rule, so
that is what it does now.

Fixed, all four fields to zero, from one fact about upstream. `GetImageDisplayParent` (`DtoService.cs:1522`) sends a `MusicAlbum` to the **artist it names**, not to the folder above it — and that artist is looked up in a batch (`LinkedChildrenService.FindArtists`) whose query does not include the images navigation. So an album that names an artist gets an image-less row, borrows nothing, and the walk ends there, because `MusicArtist` does not inherit images. Only an album naming an artist no row answers falls back to its real ancestor. That single fact accounts for all 6,330 excess `ParentBackdrop*`/`ParentLogo*` items. Beside it: `AddInheritedImages` returns early unless the item itself supports inherited images (true only for audio, albums, videos, seasons and folders — `BaseItem`'s default is false), `AlbumPrimaryImageTag` comes from the track's own album entity, and a blurhash is filed only when the column is non-empty. | field | before | after | |---|---|---| | `ImageBlurHashes` | 5,572 | **0** | | `ParentBackdropImageTags` / `ItemId` | 3,297 | **0** | | `ParentLogoImageTag` / `ItemId` | 3,033 | **0** | | `AlbumPrimaryImageTag` | 2,722 | **0** | The reading was validated by simulating upstream's whole walk against the database: it reproduces `ParentLogoItemId`, `ParentThumbItemId` and `ParentBackdropItemId` for all 21,895 items with **0 mismatches**, and ablating either the album-to-artist redirect or the image-less-batch rule reproduces the reported counts exactly. One regression this caused and fixed in the same branch: search hints derived their backdrop from the borrowed fields, which the tighter walk emptied for 7 tracks. Upstream's hint reads the raw parent chain with no inheritance rule, so that is what it does now.
Sign in to join this conversation.
No description provided.