Fixed: Speed up initial movie load when opening the UI

pull/5211/head
ta264 4 years ago committed by Qstick
parent f917d0e9bc
commit 0a8dd85856

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
@ -40,15 +41,16 @@ namespace NzbDrone.Core.Test.MediaCoverTests
new MediaCover.MediaCover { CoverType = MediaCoverTypes.Banner } new MediaCover.MediaCover { CoverType = MediaCoverTypes.Banner }
}; };
Mocker.GetMock<IDiskProvider>().Setup(c => c.FileGetLastWrite(It.IsAny<string>())) var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "H264_sample.mp4");
.Returns(new DateTime(1234)); var fileInfo = new FileInfo(path);
Mocker.GetMock<IDiskProvider>().Setup(c => c.FileExists(It.IsAny<string>())) Mocker.GetMock<IDiskProvider>()
.Returns(true); .Setup(c => c.GetFileInfo(It.IsAny<string>()))
.Returns(fileInfo);
Subject.ConvertToLocalUrls(12, covers); Subject.ConvertToLocalUrls(12, covers);
covers.Single().Url.Should().Be("/MediaCover/12/banner.jpg?lastWrite=1234"); covers.Single().Url.Should().Be($"/MediaCover/12/banner.jpg?lastWrite={fileInfo.LastWriteTimeUtc.Ticks}");
} }
[Test] [Test]
@ -59,6 +61,13 @@ namespace NzbDrone.Core.Test.MediaCoverTests
new MediaCover.MediaCover { CoverType = MediaCoverTypes.Banner } new MediaCover.MediaCover { CoverType = MediaCoverTypes.Banner }
}; };
var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "NonExistant.mp4");
var fileInfo = new FileInfo(path);
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFileInfo(It.IsAny<string>()))
.Returns(fileInfo);
Subject.ConvertToLocalUrls(12, covers); Subject.ConvertToLocalUrls(12, covers);
covers.Single().Url.Should().Be("/MediaCover/12/banner.jpg"); covers.Single().Url.Should().Be("/MediaCover/12/banner.jpg");

@ -1,9 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using NLog; using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
@ -17,7 +19,8 @@ namespace NzbDrone.Core.MediaCover
{ {
public interface IMapCoversToLocal public interface IMapCoversToLocal
{ {
void ConvertToLocalUrls(int movieId, IEnumerable<MediaCover> covers); Dictionary<string, FileInfo> GetCoverFileInfos();
void ConvertToLocalUrls(int movieId, IEnumerable<MediaCover> covers, Dictionary<string, FileInfo> fileInfos = null);
string GetCoverPath(int movieId, MediaCoverTypes mediaCoverTypes, int? height = null); string GetCoverPath(int movieId, MediaCoverTypes mediaCoverTypes, int? height = null);
} }
@ -70,7 +73,19 @@ namespace NzbDrone.Core.MediaCover
return Path.Combine(GetMovieCoverPath(movieId), coverTypes.ToString().ToLower() + heightSuffix + ".jpg"); return Path.Combine(GetMovieCoverPath(movieId), coverTypes.ToString().ToLower() + heightSuffix + ".jpg");
} }
public void ConvertToLocalUrls(int movieId, IEnumerable<MediaCover> covers) public Dictionary<string, FileInfo> GetCoverFileInfos()
{
if (!_diskProvider.FolderExists(_coverRootFolder))
{
return new Dictionary<string, FileInfo>();
}
return _diskProvider
.GetFileInfos(_coverRootFolder, SearchOption.AllDirectories)
.ToDictionary(x => x.FullName, PathEqualityComparer.Instance);
}
public void ConvertToLocalUrls(int movieId, IEnumerable<MediaCover> covers, Dictionary<string, FileInfo> fileInfos = null)
{ {
if (movieId == 0) if (movieId == 0)
{ {
@ -90,9 +105,21 @@ namespace NzbDrone.Core.MediaCover
mediaCover.RemoteUrl = mediaCover.Url; mediaCover.RemoteUrl = mediaCover.Url;
mediaCover.Url = _configFileProvider.UrlBase + @"/MediaCover/" + movieId + "/" + mediaCover.CoverType.ToString().ToLower() + ".jpg"; mediaCover.Url = _configFileProvider.UrlBase + @"/MediaCover/" + movieId + "/" + mediaCover.CoverType.ToString().ToLower() + ".jpg";
if (_diskProvider.FileExists(filePath)) FileInfo file;
var fileExists = false;
if (fileInfos != null)
{
fileExists = fileInfos.TryGetValue(filePath, out file);
}
else
{
file = _diskProvider.GetFileInfo(filePath);
fileExists = file.Exists;
}
if (fileExists)
{ {
var lastWrite = _diskProvider.FileGetLastWrite(filePath); var lastWrite = file.LastWriteTimeUtc;
mediaCover.Url += "?lastWrite=" + lastWrite.Ticks; mediaCover.Url += "?lastWrite=" + lastWrite.Ticks;
} }
} }

@ -1,5 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using FluentValidation; using FluentValidation;
using Nancy; using Nancy;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
@ -42,21 +44,21 @@ namespace Radarr.Api.V3.Movies
private readonly IConfigService _configService; private readonly IConfigService _configService;
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster, public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
IMovieService moviesService, IMovieService moviesService,
IMovieTranslationService movieTranslationService, IMovieTranslationService movieTranslationService,
IAddMovieService addMovieService, IAddMovieService addMovieService,
IMapCoversToLocal coverMapper, IMapCoversToLocal coverMapper,
IManageCommandQueue commandQueueManager, IManageCommandQueue commandQueueManager,
IUpgradableSpecification qualityUpgradableSpecification, IUpgradableSpecification qualityUpgradableSpecification,
IConfigService configService, IConfigService configService,
RootFolderValidator rootFolderValidator, RootFolderValidator rootFolderValidator,
MappedNetworkDriveValidator mappedNetworkDriveValidator, MappedNetworkDriveValidator mappedNetworkDriveValidator,
MoviePathValidator moviesPathValidator, MoviePathValidator moviesPathValidator,
MovieExistsValidator moviesExistsValidator, MovieExistsValidator moviesExistsValidator,
MovieAncestorValidator moviesAncestorValidator, MovieAncestorValidator moviesAncestorValidator,
SystemFolderValidator systemFolderValidator, SystemFolderValidator systemFolderValidator,
ProfileExistsValidator profileExistsValidator, ProfileExistsValidator profileExistsValidator,
MovieFolderAsRootFolderValidator movieFolderAsRootFolderValidator) MovieFolderAsRootFolderValidator movieFolderAsRootFolderValidator)
: base(signalRBroadcaster) : base(signalRBroadcaster)
{ {
_moviesService = moviesService; _moviesService = moviesService;
@ -104,6 +106,8 @@ namespace Radarr.Api.V3.Movies
var moviesResources = new List<MovieResource>(); var moviesResources = new List<MovieResource>();
var configLanguage = (Language)_configService.MovieInfoLanguage; var configLanguage = (Language)_configService.MovieInfoLanguage;
Dictionary<string, FileInfo> coverFileInfos = null;
if (tmdbId > 0) if (tmdbId > 0)
{ {
var movie = _moviesService.FindByTmdbId(tmdbId); var movie = _moviesService.FindByTmdbId(tmdbId);
@ -117,18 +121,27 @@ namespace Radarr.Api.V3.Movies
} }
else else
{ {
var translations = _movieTranslationService.GetAllTranslationsForLanguage(configLanguage); var movieTask = Task.Run(() => _moviesService.GetAllMovies());
var movies = _moviesService.GetAllMovies();
var translations = _movieTranslationService
.GetAllTranslationsForLanguage(configLanguage)
.ToDictionary(x => x.MovieId);
coverFileInfos = _coverMapper.GetCoverFileInfos();
var movies = movieTask.GetAwaiter().GetResult();
moviesResources = new List<MovieResource>(movies.Count);
foreach (var movie in movies) foreach (var movie in movies)
{ {
var translation = GetMovieTranslation(translations, movie, configLanguage); var translation = GetTranslationFromDict(translations, movie, configLanguage);
moviesResources.Add(movie.ToResource(_qualityUpgradableSpecification, translation)); var resource = movie.ToResource(_qualityUpgradableSpecification, translation);
_coverMapper.ConvertToLocalUrls(resource.Id, resource.Images, coverFileInfos);
moviesResources.Add(resource);
} }
} }
MapCoversToLocal(moviesResources.ToArray());
return moviesResources; return moviesResources;
} }
@ -168,6 +181,21 @@ namespace Radarr.Api.V3.Movies
return translations.FirstOrDefault(t => t.Language == configLanguage && t.MovieId == movie.Id); return translations.FirstOrDefault(t => t.Language == configLanguage && t.MovieId == movie.Id);
} }
private MovieTranslation GetTranslationFromDict(Dictionary<int, MovieTranslation> translations, Movie movie, Language configLanguage)
{
if (configLanguage == Language.Original)
{
return new MovieTranslation
{
Title = movie.OriginalTitle,
Overview = movie.Overview
};
}
translations.TryGetValue(movie.Id, out var translation);
return translation;
}
private int AddMovie(MovieResource moviesResource) private int AddMovie(MovieResource moviesResource)
{ {
var movie = _addMovieService.AddMovie(moviesResource.ToModel()); var movie = _addMovieService.AddMovie(moviesResource.ToModel());
@ -211,12 +239,9 @@ namespace Radarr.Api.V3.Movies
_moviesService.DeleteMovie(id, deleteFiles, addExclusion); _moviesService.DeleteMovie(id, deleteFiles, addExclusion);
} }
private void MapCoversToLocal(params MovieResource[] movies) private void MapCoversToLocal(MovieResource movie)
{ {
foreach (var moviesResource in movies) _coverMapper.ConvertToLocalUrls(movie.Id, movie.Images);
{
_coverMapper.ConvertToLocalUrls(moviesResource.Id, moviesResource.Images);
}
} }
public void Handle(MovieImportedEvent message) public void Handle(MovieImportedEvent message)

Loading…
Cancel
Save