Skip to content

Queue person metadata refresh instead of blocking the item request and fix ItemCounts - #17460

Merged
crobibero merged 1 commit into
jellyfin:masterfrom
Shadowghost:fix-user-items
Aug 1, 2026
Merged

crobibero merged 1 commit into
jellyfin:masterfrom
Shadowghost:fix-user-items

Conversation

@Shadowghost

Copy link
Copy Markdown
Contributor

Changes

  • Queue the on-demand person metadata refresh instead of awaiting it.
  • Drive the by-name ItemCounts query off an item-id sub-select instead of joining the mapping table into the count.
  • Stop counting an item more than once when it is mapped more than once. An actor who also directed a film has two PeopleBaseItemMap rows for it, and the old join counted that film twice.

Code assistance
Claude Opus 5 was used for the tests

Issues
Fixes #17457

@Shadowghost Shadowghost moved this to Review in Jellyfin v12 Jul 27, 2026
@Shadowghost
Shadowghost requested a review from a team July 27, 2026 21:11
@jellyfin-bot

Copy link
Copy Markdown
Contributor

Jellyfin API (v 12.0.0)


Result


No differences. Specifications are equivalent

@sonarqubecloud

Copy link
Copy Markdown

}

await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false);
QueueRefreshOnDemandIfNeeded(item);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this change mean that the DTO returned from GettBaseItemDto is essentially guaranteed to be the unchanged-yet existing data? Seem that make the return value of the GetItem pretty useless. We should likely set the right expectation by not returning a DTO from this method, since it's a "before" state.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's different behavior to any other endpoint we have and it is essentially a library refresh every time somebody calls the endpoint.
IMO implicitly refreshing data and not returning what is currently in the DB is bad practice

public ActionResult<BaseItemDto> GetItemLegacy(
[FromRoute, Required] Guid userId,
[FromRoute, Required] Guid itemId)
=> GetItem(userId, itemId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The legacy version likely should really be doing a "wait" until the queue refresh finishes, so it isn't returning the "before" DTO...

@enter-a-random-username

Copy link
Copy Markdown
Contributor

Tested a bit

  • Person search is now similar to all others requests
  • Favorites is faster as well, still 2.5x slower with 0 entries (never marked a person as favorite)
  • Menu opens faster as well and down to ~450ms compared to 30-40ms for an episode or series. (I usually want to change the image and not refresh or edit the other metadata)

It is a big improvement, and I guess a similar time could only be achieved if a parameter is added to do less work for places that do not require the information.

@theguymadmax theguymadmax moved this from Review to Approved in Jellyfin v12 Aug 1, 2026
@crobibero
crobibero merged commit 341c19b into jellyfin:master Aug 1, 2026
16 checks passed
@github-project-automation github-project-automation Bot moved this from Approved to Done in Jellyfin v12 Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Fast /Users/<UUID>/Items/<UUID> enpoint, except person

7 participants