New: Faster initial movie load

This commit is contained in:
ta264 2021-02-03 21:26:10 +00:00 committed by Qstick
parent f03dfda2f0
commit 621edba82d
3 changed files with 49 additions and 14 deletions

View File

@ -21,6 +21,7 @@ namespace NzbDrone.Core.MediaCover
{
Dictionary<string, FileInfo> GetCoverFileInfos();
void ConvertToLocalUrls(int movieId, IEnumerable<MediaCover> covers, Dictionary<string, FileInfo> fileInfos = null);
void ConvertToLocalUrls(IEnumerable<Tuple<int, IEnumerable<MediaCover>>> items, Dictionary<string, FileInfo> coverFileInfos);
string GetCoverPath(int movieId, MediaCoverTypes mediaCoverTypes, int? height = null);
}
@ -126,6 +127,14 @@ namespace NzbDrone.Core.MediaCover
}
}
public void ConvertToLocalUrls(IEnumerable<Tuple<int, IEnumerable<MediaCover>>> items, Dictionary<string, FileInfo> coverFileInfos)
{
foreach (var movie in items)
{
ConvertToLocalUrls(movie.Item1, movie.Item2, coverFileInfos);
}
}
private string GetMovieCoverPath(int movieId)
{
return Path.Combine(_coverRootFolder, movieId.ToString());

View File

@ -37,12 +37,16 @@ namespace NzbDrone.Core.Movies
public class MovieRepository : BasicRepository<Movie>, IMovieRepository
{
private readonly IProfileRepository _profileRepository;
private readonly IAlternativeTitleRepository _alternativeTitleRepository;
public MovieRepository(IMainDatabase database,
IProfileRepository profileRepository,
IAlternativeTitleRepository alternativeTitleRepository,
IEventAggregator eventAggregator)
: base(database, eventAggregator)
{
_profileRepository = profileRepository;
_alternativeTitleRepository = alternativeTitleRepository;
}
protected override SqlBuilder Builder() => new SqlBuilder()
@ -88,20 +92,30 @@ namespace NzbDrone.Core.Movies
public override IEnumerable<Movie> All()
{
// the skips the join on profile and populates manually
// to avoid repeatedly deserializing the same profile
// the skips the join on profile and alternative title and populates manually
// to avoid repeatedly deserializing the same profile / movie
var builder = new SqlBuilder()
.LeftJoin<Movie, AlternativeTitle>((m, t) => m.Id == t.MovieId)
.LeftJoin<Movie, MovieFile>((m, f) => m.Id == f.MovieId);
var movieDictionary = new Dictionary<int, Movie>();
var profiles = _profileRepository.All().ToDictionary(x => x.Id);
var titles = _alternativeTitleRepository.All()
.GroupBy(x => x.MovieId)
.ToDictionary(x => x.Key, y => y.ToList());
_ = _database.QueryJoined<Movie, AlternativeTitle, MovieFile>(
return _database.QueryJoined<Movie, MovieFile>(
builder,
(movie, altTitle, file) => Map(movieDictionary, movie, profiles[movie.ProfileId], altTitle, file));
(movie, file) =>
{
movie.MovieFile = file;
movie.Profile = profiles[movie.ProfileId];
return movieDictionary.Values.ToList();
if (titles.TryGetValue(movie.Id, out var altTitles))
{
movie.AlternativeTitles = altTitles;
}
return movie;
});
}
public bool MoviePathExists(string path)

View File

@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using FluentValidation;
using Nancy;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Datastore.Events;
@ -42,6 +44,7 @@ namespace Radarr.Api.V3.Movies
private readonly IManageCommandQueue _commandQueueManager;
private readonly IUpgradableSpecification _qualityUpgradableSpecification;
private readonly IConfigService _configService;
private readonly Logger _logger;
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
IMovieService moviesService,
@ -59,7 +62,8 @@ namespace Radarr.Api.V3.Movies
RecycleBinValidator recycleBinValidator,
SystemFolderValidator systemFolderValidator,
ProfileExistsValidator profileExistsValidator,
MovieFolderAsRootFolderValidator movieFolderAsRootFolderValidator)
MovieFolderAsRootFolderValidator movieFolderAsRootFolderValidator,
Logger logger)
: base(signalRBroadcaster)
{
_moviesService = moviesService;
@ -69,6 +73,7 @@ namespace Radarr.Api.V3.Movies
_configService = configService;
_coverMapper = coverMapper;
_commandQueueManager = commandQueueManager;
_logger = logger;
GetResourceAll = AllMovie;
GetResourceById = GetMovie;
@ -122,11 +127,13 @@ namespace Radarr.Api.V3.Movies
{
var configLanguage = (Language)_configService.MovieInfoLanguage;
var availDelay = _configService.AvailabilityDelay;
var movieTask = Task.Run(() => _moviesService.GetAllMovies());
var translations = _movieTranslationService
.GetAllTranslationsForLanguage(configLanguage)
.ToDictionary(x => x.MovieId);
.GetAllTranslationsForLanguage(configLanguage);
var tdict = translations.ToDictionary(x => x.MovieId);
coverFileInfos = _coverMapper.GetCoverFileInfos();
@ -136,13 +143,13 @@ namespace Radarr.Api.V3.Movies
foreach (var movie in movies)
{
var translation = GetTranslationFromDict(translations, movie, configLanguage);
var resource = movie.ToResource(availDelay, translation, _qualityUpgradableSpecification);
_coverMapper.ConvertToLocalUrls(resource.Id, resource.Images, coverFileInfos);
moviesResources.Add(resource);
var translation = GetTranslationFromDict(tdict, movie, configLanguage);
moviesResources.Add(movie.ToResource(availDelay, translation, _qualityUpgradableSpecification));
}
}
MapCoversToLocal(moviesResources, coverFileInfos);
return moviesResources;
}
@ -249,6 +256,11 @@ namespace Radarr.Api.V3.Movies
_coverMapper.ConvertToLocalUrls(movie.Id, movie.Images);
}
private void MapCoversToLocal(IEnumerable<MovieResource> movies, Dictionary<string, FileInfo> coverFileInfos)
{
_coverMapper.ConvertToLocalUrls(movies.Select(x => Tuple.Create(x.Id, x.Images.AsEnumerable())), coverFileInfos);
}
public void Handle(MovieImportedEvent message)
{
var availDelay = _configService.AvailabilityDelay;