Batch alternate version detection in DtoService to remove MediaSourceCount N+1

Browsing a page of videos with the MediaSourceCount field ran one alternate
version query per item, each opening a fresh DbContext. On a large library that
turned a single page into hundreds of sequential round trips and made the Items
endpoint take tens of seconds while holding a request thread the whole time.

Detect which videos own alternate versions once per page with a single query,
mirroring the existing people batch. Videos absent from that set have a single
media source, so the per item lookups are skipped for the common case. Behavior
is unchanged: a video with no alternates already resolved to a count of one.

Adds a regression test asserting the count resolves from the batch and the per
item lookups are never called.
This commit is contained in:
brandon
2026-08-07 22:51:45 -04:00
parent 70ffd25b50
commit c091ffdc6b
6 changed files with 123 additions and 12 deletions
@@ -59,6 +59,27 @@ public class LinkedChildrenService : ILinkedChildrenService
.ToArray();
}
/// <inheritdoc/>
public IReadOnlySet<Guid> GetItemsWithAlternateVersions(IReadOnlyList<Guid> itemIds)
{
if (itemIds.Count == 0)
{
return new HashSet<Guid>();
}
using var dbContext = _dbProvider.CreateDbContext();
var parentIds = dbContext.LinkedChildren
.Where(lc => (lc.ChildType == DbLinkedChildType.LocalAlternateVersion
|| lc.ChildType == DbLinkedChildType.LinkedAlternateVersion)
&& itemIds.Contains(lc.ParentId))
.Select(lc => lc.ParentId)
.Distinct()
.ToArray();
return parentIds.ToHashSet();
}
/// <inheritdoc/>
public IReadOnlyDictionary<string, MusicArtist[]> FindArtists(IReadOnlyList<string> artistNames)
{