Cache root folders and improve getting disk space for series path roots

This commit is contained in:
Mark McDowall 2024-07-24 22:07:51 -07:00
parent 578f95546b
commit d05df97821
2 changed files with 36 additions and 14 deletions

View File

@ -6,6 +6,7 @@ using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.RootFolders;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.DiskSpace
@ -18,14 +19,16 @@ namespace NzbDrone.Core.DiskSpace
public class DiskSpaceService : IDiskSpaceService
{
private readonly ISeriesService _seriesService;
private readonly IRootFolderService _rootFolderService;
private readonly IDiskProvider _diskProvider;
private readonly Logger _logger;
private static readonly Regex _regexSpecialDrive = new Regex("^/var/lib/(docker|rancher|kubelet)(/|$)|^/(boot|etc)(/|$)|/docker(/var)?/aufs(/|$)", RegexOptions.Compiled);
public DiskSpaceService(ISeriesService seriesService, IDiskProvider diskProvider, Logger logger)
public DiskSpaceService(ISeriesService seriesService, IRootFolderService rootFolderService, IDiskProvider diskProvider, Logger logger)
{
_seriesService = seriesService;
_rootFolderService = rootFolderService;
_diskProvider = diskProvider;
_logger = logger;
}
@ -43,9 +46,15 @@ namespace NzbDrone.Core.DiskSpace
private IEnumerable<string> GetSeriesRootPaths()
{
// Get all series paths and find the correct root folder for each. For each unique root folder path,
// ensure the path exists and get its path root and return all unique path roots.
return _seriesService.GetAllSeriesPaths()
.Where(s => s.Value.IsPathValid(PathValidationType.CurrentOs) && _diskProvider.FolderExists(s.Value))
.Select(s => _diskProvider.GetPathRoot(s.Value))
.Where(s => s.Value.IsPathValid(PathValidationType.CurrentOs))
.Select(s => _rootFolderService.GetBestRootFolderPath(s.Value))
.Distinct()
.Where(r => _diskProvider.FolderExists(r))
.Select(r => _diskProvider.GetPathRoot(r))
.Distinct();
}

View File

@ -5,6 +5,7 @@ using System.Linq;
using System.Threading.Tasks;
using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Organizer;
@ -30,6 +31,8 @@ namespace NzbDrone.Core.RootFolders
private readonly INamingConfigService _namingConfigService;
private readonly Logger _logger;
private readonly ICached<string> _cache;
private static readonly HashSet<string> SpecialFolders = new HashSet<string>
{
"$recycle.bin",
@ -47,6 +50,7 @@ namespace NzbDrone.Core.RootFolders
IDiskProvider diskProvider,
ISeriesRepository seriesRepository,
INamingConfigService namingConfigService,
ICacheManager cacheManager,
Logger logger)
{
_rootFolderRepository = rootFolderRepository;
@ -54,6 +58,8 @@ namespace NzbDrone.Core.RootFolders
_seriesRepository = seriesRepository;
_namingConfigService = namingConfigService;
_logger = logger;
_cache = cacheManager.GetCache<string>(GetType());
}
public List<RootFolder> All()
@ -110,19 +116,21 @@ namespace NzbDrone.Core.RootFolders
if (!_diskProvider.FolderWritable(rootFolder.Path))
{
throw new UnauthorizedAccessException(string.Format("Root folder path '{0}' is not writable by user '{1}'", rootFolder.Path, Environment.UserName));
throw new UnauthorizedAccessException($"Root folder path '{rootFolder.Path}' is not writable by user '{Environment.UserName}'");
}
_rootFolderRepository.Insert(rootFolder);
var seriesPaths = _seriesRepository.AllSeriesPaths();
GetDetails(rootFolder, seriesPaths, true);
_cache.Clear();
return rootFolder;
}
public void Remove(int id)
{
_cache.Clear();
_rootFolderRepository.Delete(id);
}
@ -186,16 +194,7 @@ namespace NzbDrone.Core.RootFolders
public string GetBestRootFolderPath(string path)
{
var possibleRootFolder = All().Where(r => r.Path.IsParentPath(path)).MaxBy(r => r.Path.Length);
if (possibleRootFolder == null)
{
var osPath = new OsPath(path);
return osPath.Directory.ToString().TrimEnd(osPath.IsUnixPath ? '/' : '\\');
}
return possibleRootFolder?.Path;
return _cache.Get(path, () => GetBestRootFolderPathInternal(path), TimeSpan.FromDays(1));
}
private void GetDetails(RootFolder rootFolder, Dictionary<int, string> seriesPaths, bool timeout)
@ -211,5 +210,19 @@ namespace NzbDrone.Core.RootFolders
}
}).Wait(timeout ? 5000 : -1);
}
private string GetBestRootFolderPathInternal(string path)
{
var possibleRootFolder = All().Where(r => r.Path.IsParentPath(path)).MaxBy(r => r.Path.Length);
if (possibleRootFolder == null)
{
var osPath = new OsPath(path);
return osPath.Directory.ToString().TrimEnd(osPath.IsUnixPath ? '/' : '\\');
}
return possibleRootFolder.Path;
}
}
}