Improve use of All() and speedup Unmapped Folder matching

Co-authored-by: ta264 <ta264@users.noreply.github.com>
This commit is contained in:
Qstick 2020-10-18 17:59:26 -04:00 committed by GitHub
parent 19f724dcd9
commit 897673b459
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 51 additions and 30 deletions

View File

@ -47,11 +47,11 @@ namespace NzbDrone.Core.Test.DiskSpace
GivenSeries(); GivenSeries();
} }
private void GivenSeries(params Series[] series) private void GivenSeries(params string[] seriesPaths)
{ {
Mocker.GetMock<ISeriesService>() Mocker.GetMock<ISeriesService>()
.Setup(v => v.GetAllSeries()) .Setup(v => v.GetAllSeriesPaths())
.Returns(series.ToList()); .Returns(seriesPaths.ToList());
} }
private void GivenExistingFolder(string folder) private void GivenExistingFolder(string folder)
@ -64,7 +64,7 @@ namespace NzbDrone.Core.Test.DiskSpace
[Test] [Test]
public void should_check_diskspace_for_series_folders() public void should_check_diskspace_for_series_folders()
{ {
GivenSeries(new Series { Path = _seriesFolder }); GivenSeries(_seriesFolder);
GivenExistingFolder(_seriesFolder); GivenExistingFolder(_seriesFolder);
@ -76,7 +76,7 @@ namespace NzbDrone.Core.Test.DiskSpace
[Test] [Test]
public void should_check_diskspace_for_same_root_folder_only_once() public void should_check_diskspace_for_same_root_folder_only_once()
{ {
GivenSeries(new Series { Path = _seriesFolder }, new Series { Path = _seriesFolder2 }); GivenSeries(_seriesFolder, _seriesFolder2);
GivenExistingFolder(_seriesFolder); GivenExistingFolder(_seriesFolder);
GivenExistingFolder(_seriesFolder2); GivenExistingFolder(_seriesFolder2);
@ -92,7 +92,7 @@ namespace NzbDrone.Core.Test.DiskSpace
[Test] [Test]
public void should_not_check_diskspace_for_missing_series_folders() public void should_not_check_diskspace_for_missing_series_folders()
{ {
GivenSeries(new Series { Path = _seriesFolder }); GivenSeries(_seriesFolder);
var freeSpace = Subject.GetFreeSpace(); var freeSpace = Subject.GetFreeSpace();

View File

@ -20,8 +20,8 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
.ToList(); .ToList();
Mocker.GetMock<ISeriesService>() Mocker.GetMock<ISeriesService>()
.Setup(s => s.GetAllSeries()) .Setup(s => s.GetAllSeriesPaths())
.Returns(series); .Returns(series.Select(s => s.Path).ToList());
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Setup(s => s.GetParentFolder(series.First().Path)) .Setup(s => s.GetParentFolder(series.First().Path))
@ -36,8 +36,8 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
public void should_not_return_error_when_no_series() public void should_not_return_error_when_no_series()
{ {
Mocker.GetMock<ISeriesService>() Mocker.GetMock<ISeriesService>()
.Setup(s => s.GetAllSeries()) .Setup(s => s.GetAllSeriesPaths())
.Returns(new List<Series>()); .Returns(new List<string>());
Subject.Check().ShouldBeOk(); Subject.Check().ShouldBeOk();
} }

View File

@ -44,6 +44,10 @@ namespace NzbDrone.Core.Test.RootFolderTests
[TestCase("//server//folder")] [TestCase("//server//folder")]
public void should_be_able_to_add_root_dir(string path) public void should_be_able_to_add_root_dir(string path)
{ {
Mocker.GetMock<ISeriesRepository>()
.Setup(s => s.AllSeriesPaths())
.Returns(new List<string>());
var root = new RootFolder { Path = path.AsOsAgnostic() }; var root = new RootFolder { Path = path.AsOsAgnostic() };
Subject.Add(root); Subject.Add(root);
@ -124,9 +128,9 @@ namespace NzbDrone.Core.Test.RootFolderTests
.Setup(s => s.Get(It.IsAny<int>())) .Setup(s => s.Get(It.IsAny<int>()))
.Returns(rootFolder); .Returns(rootFolder);
Mocker.GetMock<ISeriesService>() Mocker.GetMock<ISeriesRepository>()
.Setup(s => s.GetAllSeries()) .Setup(s => s.AllSeriesPaths())
.Returns(new List<Series>()); .Returns(new List<string>());
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Setup(s => s.GetDirectories(rootFolder.Path)) .Setup(s => s.GetDirectories(rootFolder.Path))

View File

@ -42,9 +42,9 @@ namespace NzbDrone.Core.DiskSpace
private IEnumerable<string> GetSeriesRootPaths() private IEnumerable<string> GetSeriesRootPaths()
{ {
return _seriesService.GetAllSeries() return _seriesService.GetAllSeriesPaths()
.Where(s => _diskProvider.FolderExists(s.Path)) .Where(s => _diskProvider.FolderExists(s))
.Select(s => _diskProvider.GetPathRoot(s.Path)) .Select(s => _diskProvider.GetPathRoot(s))
.Distinct(); .Distinct();
} }

View File

@ -19,8 +19,8 @@ namespace NzbDrone.Core.HealthCheck.Checks
public override HealthCheck Check() public override HealthCheck Check()
{ {
// Not best for optimization but due to possible symlinks and junctions, we get mounts based on series path so internals can handle mount resolution. // Not best for optimization but due to possible symlinks and junctions, we get mounts based on series path so internals can handle mount resolution.
var mounts = _seriesService.GetAllSeries() var mounts = _seriesService.GetAllSeriesPaths()
.Select(series => _diskProvider.GetMount(series.Path)) .Select(s => _diskProvider.GetMount(s))
.Where(m => m != null && m.MountOptions != null && m.MountOptions.IsReadOnly) .Where(m => m != null && m.MountOptions != null && m.MountOptions.IsReadOnly)
.DistinctBy(m => m.RootDirectory) .DistinctBy(m => m.RootDirectory)
.ToList(); .ToList();

View File

@ -1,4 +1,6 @@
using System.Diagnostics;
using System.Linq; using System.Linq;
using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.RootFolders; using NzbDrone.Core.RootFolders;
@ -26,9 +28,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
public override HealthCheck Check() public override HealthCheck Check()
{ {
var rootFolders = _seriesService.GetAllSeries() var rootFolders = _seriesService.GetAllSeriesPaths().Select(s => _rootFolderService.GetBestRootFolderPath(s)).Distinct();
.Select(s => _rootFolderService.GetBestRootFolderPath(s.Path))
.Distinct();
var missingRootFolders = rootFolders.Where(s => !_diskProvider.FolderExists(s)) var missingRootFolders = rootFolders.Where(s => !_diskProvider.FolderExists(s))
.ToList(); .ToList();

View File

@ -63,6 +63,7 @@ namespace NzbDrone.Core.RootFolders
public List<RootFolder> AllWithUnmappedFolders() public List<RootFolder> AllWithUnmappedFolders()
{ {
var rootFolders = _rootFolderRepository.All().ToList(); var rootFolders = _rootFolderRepository.All().ToList();
var seriesPaths = _seriesRepository.AllSeriesPaths();
rootFolders.ForEach(folder => rootFolders.ForEach(folder =>
{ {
@ -70,7 +71,7 @@ namespace NzbDrone.Core.RootFolders
{ {
if (folder.Path.IsPathValid()) if (folder.Path.IsPathValid())
{ {
GetDetails(folder, true); GetDetails(folder, seriesPaths, true);
} }
} }
//We don't want an exception to prevent the root folders from loading in the UI, so they can still be deleted //We don't want an exception to prevent the root folders from loading in the UI, so they can still be deleted
@ -109,8 +110,9 @@ namespace NzbDrone.Core.RootFolders
} }
_rootFolderRepository.Insert(rootFolder); _rootFolderRepository.Insert(rootFolder);
var seriesPaths = _seriesRepository.AllSeriesPaths();
GetDetails(rootFolder, true); GetDetails(rootFolder, seriesPaths, true);
return rootFolder; return rootFolder;
} }
@ -120,7 +122,7 @@ namespace NzbDrone.Core.RootFolders
_rootFolderRepository.Delete(id); _rootFolderRepository.Delete(id);
} }
private List<UnmappedFolder> GetUnmappedFolders(string path) private List<UnmappedFolder> GetUnmappedFolders(string path, List<string> seriesPaths)
{ {
_logger.Debug("Generating list of unmapped folders"); _logger.Debug("Generating list of unmapped folders");
@ -130,7 +132,6 @@ namespace NzbDrone.Core.RootFolders
} }
var results = new List<UnmappedFolder>(); var results = new List<UnmappedFolder>();
var series = _seriesRepository.All().ToList();
if (!_diskProvider.FolderExists(path)) if (!_diskProvider.FolderExists(path))
{ {
@ -139,7 +140,7 @@ namespace NzbDrone.Core.RootFolders
} }
var possibleSeriesFolders = _diskProvider.GetDirectories(path).ToList(); var possibleSeriesFolders = _diskProvider.GetDirectories(path).ToList();
var unmappedFolders = possibleSeriesFolders.Except(series.Select(s => s.Path), PathEqualityComparer.Instance).ToList(); var unmappedFolders = possibleSeriesFolders.Except(seriesPaths, PathEqualityComparer.Instance).ToList();
foreach (string unmappedFolder in unmappedFolders) foreach (string unmappedFolder in unmappedFolders)
{ {
@ -157,7 +158,9 @@ namespace NzbDrone.Core.RootFolders
public RootFolder Get(int id, bool timeout) public RootFolder Get(int id, bool timeout)
{ {
var rootFolder = _rootFolderRepository.Get(id); var rootFolder = _rootFolderRepository.Get(id);
GetDetails(rootFolder, timeout); var seriesPaths = _seriesRepository.AllSeriesPaths();
GetDetails(rootFolder, seriesPaths, timeout);
return rootFolder; return rootFolder;
} }
@ -176,7 +179,7 @@ namespace NzbDrone.Core.RootFolders
return possibleRootFolder.Path; return possibleRootFolder.Path;
} }
private void GetDetails(RootFolder rootFolder, bool timeout) private void GetDetails(RootFolder rootFolder, List<string> seriesPaths, bool timeout)
{ {
Task.Run(() => Task.Run(() =>
{ {
@ -185,7 +188,7 @@ namespace NzbDrone.Core.RootFolders
rootFolder.Accessible = true; rootFolder.Accessible = true;
rootFolder.FreeSpace = _diskProvider.GetAvailableSpace(rootFolder.Path); rootFolder.FreeSpace = _diskProvider.GetAvailableSpace(rootFolder.Path);
rootFolder.TotalSpace = _diskProvider.GetTotalSize(rootFolder.Path); rootFolder.TotalSpace = _diskProvider.GetTotalSize(rootFolder.Path);
rootFolder.UnmappedFolders = GetUnmappedFolders(rootFolder.Path); rootFolder.UnmappedFolders = GetUnmappedFolders(rootFolder.Path, seriesPaths);
} }
}).Wait(timeout ? 5000 : -1); }).Wait(timeout ? 5000 : -1);
} }

View File

@ -16,6 +16,7 @@ namespace NzbDrone.Core.Tv
Series FindByTvdbId(int tvdbId); Series FindByTvdbId(int tvdbId);
Series FindByTvRageId(int tvRageId); Series FindByTvRageId(int tvRageId);
Series FindByPath(string path); Series FindByPath(string path);
List<string> AllSeriesPaths();
} }
public class SeriesRepository : BasicRepository<Series>, ISeriesRepository public class SeriesRepository : BasicRepository<Series>, ISeriesRepository
@ -78,6 +79,13 @@ namespace NzbDrone.Core.Tv
.FirstOrDefault(); .FirstOrDefault();
} }
public List<string> AllSeriesPaths()
{
var mapper = _database.GetDataMapper();
return mapper.Query<string>("SELECT Path from Series");
}
private Series ReturnSingleSeriesOrThrow(List<Series> series) private Series ReturnSingleSeriesOrThrow(List<Series> series)
{ {
if (series.Count == 0) if (series.Count == 0)

View File

@ -24,6 +24,7 @@ namespace NzbDrone.Core.Tv
Series FindByPath(string path); Series FindByPath(string path);
void DeleteSeries(int seriesId, bool deleteFiles, bool addImportListExclusion); void DeleteSeries(int seriesId, bool deleteFiles, bool addImportListExclusion);
List<Series> GetAllSeries(); List<Series> GetAllSeries();
List<string> GetAllSeriesPaths();
List<Series> AllForTag(int tagId); List<Series> AllForTag(int tagId);
Series UpdateSeries(Series series, bool updateEpisodesToMatchSeason = true, bool publishUpdatedEvent = true); Series UpdateSeries(Series series, bool updateEpisodesToMatchSeason = true, bool publishUpdatedEvent = true);
List<Series> UpdateSeries(List<Series> series, bool useExistingRelativeFolder); List<Series> UpdateSeries(List<Series> series, bool useExistingRelativeFolder);
@ -157,6 +158,11 @@ namespace NzbDrone.Core.Tv
return _seriesRepository.All().ToList(); return _seriesRepository.All().ToList();
} }
public List<string> GetAllSeriesPaths()
{
return _seriesRepository.AllSeriesPaths();
}
public List<Series> AllForTag(int tagId) public List<Series> AllForTag(int tagId)
{ {
return GetAllSeries().Where(s => s.Tags.Contains(tagId)) return GetAllSeries().Where(s => s.Tags.Contains(tagId))

View File

@ -19,7 +19,7 @@ namespace NzbDrone.Core.Validation.Paths
{ {
if (context.PropertyValue == null) return true; if (context.PropertyValue == null) return true;
return !_seriesService.GetAllSeries().Any(s => context.PropertyValue.ToString().IsParentPath(s.Path)); return !_seriesService.GetAllSeriesPaths().Any(s => context.PropertyValue.ToString().IsParentPath(s));
} }
} }
} }