From 696bb845a568dd26792efd8f6142347997ed0582 Mon Sep 17 00:00:00 2001 From: Qstick Date: Thu, 2 Jun 2022 19:31:42 -0500 Subject: [PATCH] Fixed: Speed up Collections API Endpoint --- .../Movies/MovieMetadataRepository.cs | 40 +++++++++++++++++++ .../Movies/MovieMetadataService.cs | 6 +++ .../Collections/CollectionController.cs | 30 +++++++++++++- .../ImportLists/ImportListMoviesController.cs | 18 ++++++--- 4 files changed, 86 insertions(+), 8 deletions(-) diff --git a/src/NzbDrone.Core/Movies/MovieMetadataRepository.cs b/src/NzbDrone.Core/Movies/MovieMetadataRepository.cs index 180db057e..bce138878 100644 --- a/src/NzbDrone.Core/Movies/MovieMetadataRepository.cs +++ b/src/NzbDrone.Core/Movies/MovieMetadataRepository.cs @@ -2,7 +2,9 @@ using System.Linq; using NLog; using NzbDrone.Core.Datastore; +using NzbDrone.Core.Languages; using NzbDrone.Core.Messaging.Events; +using NzbDrone.Core.Movies.Translations; namespace NzbDrone.Core.Movies { @@ -10,6 +12,7 @@ public interface IMovieMetadataRepository : IBasicRepository { MovieMetadata FindByTmdbId(int tmdbId); List FindById(List tmdbIds); + List GetMoviesWithCollections(); List GetMoviesByCollectionTmdbId(int collectionId); bool UpsertMany(List data); } @@ -34,6 +37,43 @@ public List FindById(List tmdbIds) return Query(x => Enumerable.Contains(tmdbIds, x.TmdbId)); } + public List GetMoviesWithCollections() + { + var movieDictionary = new Dictionary(); + + var builder = new SqlBuilder(_database.DatabaseType) + .LeftJoin((mm, t) => mm.Id == t.MovieMetadataId) + .Where(x => x.CollectionTmdbId > 0); + + _ = _database.QueryJoined( + builder, + (metadata, translation) => + { + MovieMetadata movieEntry; + + if (!movieDictionary.TryGetValue(metadata.Id, out movieEntry)) + { + movieEntry = metadata; + movieDictionary.Add(movieEntry.Id, movieEntry); + } + + if (translation != null) + { + movieEntry.Translations.Add(translation); + } + else + { + // Add a translation to avoid filename builder making another call thinking translations are not loaded + // Optimize this later by pulling translations with metadata always + movieEntry.Translations.Add(new MovieTranslation { Title = movieEntry.Title, Language = Language.English }); + } + + return movieEntry; + }); + + return movieDictionary.Values.ToList(); + } + public List GetMoviesByCollectionTmdbId(int collectionId) { return Query(x => x.CollectionTmdbId == collectionId); diff --git a/src/NzbDrone.Core/Movies/MovieMetadataService.cs b/src/NzbDrone.Core/Movies/MovieMetadataService.cs index 30a0a9d23..b0aab7ff1 100644 --- a/src/NzbDrone.Core/Movies/MovieMetadataService.cs +++ b/src/NzbDrone.Core/Movies/MovieMetadataService.cs @@ -6,6 +6,7 @@ public interface IMovieMetadataService { MovieMetadata Get(int id); MovieMetadata FindByTmdbId(int tmdbid); + List GetMoviesWithCollections(); List GetMoviesByCollectionTmdbId(int collectionId); bool Upsert(MovieMetadata movie); bool UpsertMany(List movies); @@ -25,6 +26,11 @@ public MovieMetadata FindByTmdbId(int tmdbid) return _movieMetadataRepository.FindByTmdbId(tmdbid); } + public List GetMoviesWithCollections() + { + return _movieMetadataRepository.GetMoviesWithCollections(); + } + public List GetMoviesByCollectionTmdbId(int collectionId) { return _movieMetadataRepository.GetMoviesByCollectionTmdbId(collectionId); diff --git a/src/Radarr.Api.V3/Collections/CollectionController.cs b/src/Radarr.Api.V3/Collections/CollectionController.cs index 41f9823db..9732d8d17 100644 --- a/src/Radarr.Api.V3/Collections/CollectionController.cs +++ b/src/Radarr.Api.V3/Collections/CollectionController.cs @@ -24,18 +24,21 @@ public class CollectionController : RestControllerWithSignalR GetCollections() { - return _collectionService.GetAllCollections().Select(c => MapToResource(c)).ToList(); + var collectionMovies = _movieMetadataService.GetMoviesWithCollections(); + + return MapToResource(_collectionService.GetAllCollections(), collectionMovies).ToList(); } [RestPutById] @@ -92,6 +97,27 @@ public ActionResult UpdateCollections(CollectionUpdateResource collectionResourc return Accepted(update); } + private IEnumerable MapToResource(List collections, List collectionMovies) + { + // Avoid calling for naming spec on every movie in filenamebuilder + var namingConfig = _namingService.GetConfig(); + + foreach (var collection in collections) + { + var resource = collection.ToResource(); + + foreach (var movie in collectionMovies.Where(m => m.CollectionTmdbId == collection.TmdbId)) + { + var movieResource = movie.ToResource(); + movieResource.Folder = _fileNameBuilder.GetMovieFolder(new Movie { MovieMetadata = movie }, namingConfig); + + resource.Movies.Add(movieResource); + } + + yield return resource; + } + } + private CollectionResource MapToResource(MovieCollection collection) { var resource = collection.ToResource(); diff --git a/src/Radarr.Api.V3/ImportLists/ImportListMoviesController.cs b/src/Radarr.Api.V3/ImportLists/ImportListMoviesController.cs index f5a646f3c..1ddeb6c38 100644 --- a/src/Radarr.Api.V3/ImportLists/ImportListMoviesController.cs +++ b/src/Radarr.Api.V3/ImportLists/ImportListMoviesController.cs @@ -24,6 +24,7 @@ public class ImportListMoviesController : Controller private readonly IImportListMovieService _listMovieService; private readonly IImportListFactory _importListFactory; private readonly IImportExclusionsService _importExclusionService; + private readonly INamingConfigService _namingService; private readonly IConfigService _configService; public ImportListMoviesController(IMovieService movieService, @@ -32,6 +33,7 @@ public ImportListMoviesController(IMovieService movieService, IImportListMovieService listMovieService, IImportListFactory importListFactory, IImportExclusionsService importExclusionsService, + INamingConfigService namingService, IConfigService configService) { _movieService = movieService; @@ -40,6 +42,7 @@ public ImportListMoviesController(IMovieService movieService, _listMovieService = listMovieService; _importListFactory = importListFactory; _importExclusionService = importExclusionsService; + _namingService = namingService; _configService = configService; } @@ -91,6 +94,9 @@ public object GetDiscoverMovies(bool includeRecommendations = false) private IEnumerable MapToResource(IEnumerable movies, Language language) { + //Avoid calling for naming spec on every movie in filenamebuilder + var namingConfig = _namingService.GetConfig(); + foreach (var currentMovie in movies) { var resource = DiscoverMoviesResourceMapper.ToResource(currentMovie); @@ -104,7 +110,7 @@ private IEnumerable MapToResource(IEnumerable m resource.Title = translation?.Title ?? resource.Title; resource.Overview = translation?.Overview ?? resource.Overview; - resource.Folder = _fileNameBuilder.GetMovieFolder(currentMovie); + resource.Folder = _fileNameBuilder.GetMovieFolder(currentMovie, namingConfig); yield return resource; } @@ -112,6 +118,9 @@ private IEnumerable MapToResource(IEnumerable m private IEnumerable MapToResource(IEnumerable movies, Language language) { + // Avoid calling for naming spec on every movie in filenamebuilder + var namingConfig = _namingService.GetConfig(); + foreach (var currentMovie in movies) { var resource = DiscoverMoviesResourceMapper.ToResource(currentMovie); @@ -127,11 +136,8 @@ private IEnumerable MapToResource(IEnumerable