From 046225654af0105a3f8cf1678b1b1e8e00fd215a Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Mon, 27 Jul 2026 23:09:30 +0200 Subject: Queue person metadata refresh instead of blocking the item request and fix ItemCounts --- Jellyfin.Api/Controllers/UserLibraryController.cs | 45 +++++++++++++--------- .../Item/ItemCountService.cs | 19 +++++---- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index a718035528..ea134a4619 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -40,6 +40,7 @@ public class UserLibraryController : BaseJellyfinApiController private readonly IDtoService _dtoService; private readonly IUserViewManager _userViewManager; private readonly IFileSystem _fileSystem; + private readonly IProviderManager _providerManager; /// /// Initializes a new instance of the class. @@ -50,13 +51,15 @@ public class UserLibraryController : BaseJellyfinApiController /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public UserLibraryController( IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IDtoService dtoService, IUserViewManager userViewManager, - IFileSystem fileSystem) + IFileSystem fileSystem, + IProviderManager providerManager) { _userManager = userManager; _userDataRepository = userDataRepository; @@ -64,6 +67,7 @@ public class UserLibraryController : BaseJellyfinApiController _dtoService = dtoService; _userViewManager = userViewManager; _fileSystem = fileSystem; + _providerManager = providerManager; } /// @@ -75,7 +79,7 @@ public class UserLibraryController : BaseJellyfinApiController /// An containing the item. [HttpGet("Items/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> GetItem( + public ActionResult GetItem( [FromQuery] Guid? userId, [FromRoute, Required] Guid itemId) { @@ -94,7 +98,7 @@ public class UserLibraryController : BaseJellyfinApiController return NotFound(); } - await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false); + QueueRefreshOnDemandIfNeeded(item); var dtoOptions = new DtoOptions(); @@ -112,7 +116,7 @@ public class UserLibraryController : BaseJellyfinApiController [ProducesResponseType(StatusCodes.Status200OK)] [Obsolete("Kept for backwards compatibility")] [ApiExplorerSettings(IgnoreApi = true)] - public Task> GetItemLegacy( + public ActionResult GetItemLegacy( [FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) => GetItem(userId, itemId); @@ -639,25 +643,28 @@ public class UserLibraryController : BaseJellyfinApiController limit, groupItems); - private async Task RefreshItemOnDemandIfNeeded(BaseItem item) + private void QueueRefreshOnDemandIfNeeded(BaseItem item) { - if (item is Person) + if (item is not Person) { - var hasMetadata = !string.IsNullOrWhiteSpace(item.Overview) && item.HasImage(ImageType.Primary); - var performFullRefresh = !hasMetadata && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= 3; + return; + } - if (performFullRefresh) - { - var options = new MetadataRefreshOptions(new DirectoryService(_fileSystem)) - { - MetadataRefreshMode = MetadataRefreshMode.FullRefresh, - ImageRefreshMode = MetadataRefreshMode.FullRefresh, - ForceSave = true - }; - - await item.RefreshMetadata(options, CancellationToken.None).ConfigureAwait(false); - } + var hasMetadata = !string.IsNullOrWhiteSpace(item.Overview) && item.HasImage(ImageType.Primary); + if (hasMetadata || (DateTime.UtcNow - item.DateLastRefreshed).TotalDays < 3) + { + return; } + + _providerManager.QueueRefresh( + item.Id, + new MetadataRefreshOptions(new DirectoryService(_fileSystem)) + { + MetadataRefreshMode = MetadataRefreshMode.FullRefresh, + ImageRefreshMode = MetadataRefreshMode.FullRefresh, + ForceSave = true + }, + RefreshPriority.High); } /// diff --git a/Jellyfin.Server.Implementations/Item/ItemCountService.cs b/Jellyfin.Server.Implementations/Item/ItemCountService.cs index 604db9f839..4aa65769fd 100644 --- a/Jellyfin.Server.Implementations/Item/ItemCountService.cs +++ b/Jellyfin.Server.Implementations/Item/ItemCountService.cs @@ -141,32 +141,32 @@ public class ItemCountService : IItemCountService switch (kind) { case BaseItemKind.Person: - baseQuery = context.PeopleBaseItemMap + baseQuery = ItemsById(context, context.PeopleBaseItemMap .AsNoTracking() .Where(m => m.People.Name == item.Name) - .Select(m => m.Item); + .Select(m => m.ItemId)); break; case BaseItemKind.MusicArtist: - baseQuery = context.ItemValuesMap + baseQuery = ItemsById(context, context.ItemValuesMap .AsNoTracking() .Where(ivm => ivm.ItemValue.CleanValue == item.CleanName && (ivm.ItemValue.Type == ItemValueType.Artist || ivm.ItemValue.Type == ItemValueType.AlbumArtist)) - .Select(ivm => ivm.Item); + .Select(ivm => ivm.ItemId)); break; case BaseItemKind.Genre: case BaseItemKind.MusicGenre: - baseQuery = context.ItemValuesMap + baseQuery = ItemsById(context, context.ItemValuesMap .AsNoTracking() .Where(ivm => ivm.ItemValue.CleanValue == item.CleanName && ivm.ItemValue.Type == ItemValueType.Genre) - .Select(ivm => ivm.Item); + .Select(ivm => ivm.ItemId)); break; case BaseItemKind.Studio: - baseQuery = context.ItemValuesMap + baseQuery = ItemsById(context, context.ItemValuesMap .AsNoTracking() .Where(ivm => ivm.ItemValue.CleanValue == item.CleanName && ivm.ItemValue.Type == ItemValueType.Studios) - .Select(ivm => ivm.Item); + .Select(ivm => ivm.ItemId)); break; case BaseItemKind.Year: if (int.TryParse(item.Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var year)) @@ -254,6 +254,9 @@ public class ItemCountService : IItemCountService return result; } + private static IQueryable ItemsById(JellyfinDbContext context, IQueryable itemIds) + => context.BaseItems.AsNoTracking().Where(e => itemIds.Contains(e.Id)); + /// public int GetPlayedCount(InternalItemsQuery filter, Guid ancestorId) { -- cgit v1.2.3