From 6b8d1695297c28098924c5da18da133083ca9c92 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Bachmann Date: Wed, 1 Feb 2023 19:34:58 +0100 Subject: [PATCH 1/8] Added CleanupCollection task --- .../Collections/CollectionManager.cs | 3 +- .../Tasks/CleanupCollectionPathsTask.cs | 118 ++++++++++++++++++ .../Collections/ICollectionManager.cs | 7 ++ 3 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index b53c8ca512..20370fff5d 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -112,7 +112,8 @@ namespace Emby.Server.Implementations.Collections return Path.Combine(_appPaths.DataPath, "collections"); } - private Task GetCollectionsFolder(bool createIfNeeded) + /// + public Task GetCollectionsFolder(bool createIfNeeded) { return EnsureLibraryFolder(GetCollectionsFolderPath(), createIfNeeded); } diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs new file mode 100644 index 0000000000..8e9270a125 --- /dev/null +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Emby.Server.Implementations.Collections; +using MediaBrowser.Controller.Collections; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Tasks; +using Microsoft.Extensions.Logging; + +namespace Emby.Server.Implementations.ScheduledTasks.Tasks; + +/// +/// Deletes Path references from collections that no longer exists. +/// +public class CleanupCollectionPathsTask : IScheduledTask +{ + private readonly ILocalizationManager _localization; + private readonly ICollectionManager _collectionManager; + private readonly ILogger _logger; + private readonly IProviderManager _providerManager; + private readonly IFileSystem _fileSystem; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + /// Instance of the interface. + /// The logger. + /// The provider manager. + /// The filesystem. + public CleanupCollectionPathsTask( + ILocalizationManager localization, + ICollectionManager collectionManager, + ILogger logger, + IProviderManager providerManager, + IFileSystem fileSystem) + { + _localization = localization; + _collectionManager = collectionManager; + _logger = logger; + _providerManager = providerManager; + _fileSystem = fileSystem; + } + + /// + public string Name => _localization.GetLocalizedString("TaskCleanCollections"); + + /// + public string Key => "CleanCollections"; + + /// + public string Description => _localization.GetLocalizedString("TaskCleanCollectionsDescription"); + + /// + public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory"); + + /// + public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) + { + var collectionsFolder = await _collectionManager.GetCollectionsFolder(true).ConfigureAwait(false); + if (collectionsFolder is null) + { + _logger.LogInformation("There is no collection folder to be found."); + return; + } + + var collections = collectionsFolder.Children.OfType() + .ToArray(); + _logger.LogTrace("Found {CollectionLength} Boxsets.", collections.Length); + for (var index = 0; index < collections.Length; index++) + { + var collection = collections[index]; + _logger.LogTrace("Check Boxset {CollectionName}.", collection.Name); + var itemsToRemove = new List(); + foreach (var collectionLinkedChild in collection.LinkedChildren.ToArray()) + { + if (!File.Exists(collectionLinkedChild.Path)) + { + _logger.LogInformation("Item in boxset {0} cannot be found at {1}.", collection.Name, collectionLinkedChild.Path); + itemsToRemove.Add(collectionLinkedChild); + } + } + + if (itemsToRemove.Any()) + { + _logger.LogTrace("Update Boxset {CollectionName}.", collection.Name); + collection.LinkedChildren = collection.LinkedChildren.Except(itemsToRemove).ToArray(); + await collection.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, cancellationToken) + .ConfigureAwait(false); + + _providerManager.QueueRefresh( + collection.Id, + new MetadataRefreshOptions(new DirectoryService(_fileSystem)) + { + ForceSave = true + }, + RefreshPriority.High); + } + + progress.Report(100D / collections.Length * (index + 1)); + } + } + + /// + public IEnumerable GetDefaultTriggers() + { + return new[] { new TaskTriggerInfo() { Type = TaskTriggerInfo.TriggerStartup } }; + // return Enumerable.Empty(); + } +} diff --git a/MediaBrowser.Controller/Collections/ICollectionManager.cs b/MediaBrowser.Controller/Collections/ICollectionManager.cs index b8c33ee5a0..38a78a67b5 100644 --- a/MediaBrowser.Controller/Collections/ICollectionManager.cs +++ b/MediaBrowser.Controller/Collections/ICollectionManager.cs @@ -56,5 +56,12 @@ namespace MediaBrowser.Controller.Collections /// The user. /// IEnumerable{BaseItem}. IEnumerable CollapseItemsWithinBoxSets(IEnumerable items, User user); + + /// + /// Gets the folder where collections are stored. + /// + /// Will create the collection folder on the storage if set to true. + /// The folder instance referencing the collection storage. + Task GetCollectionsFolder(bool createIfNeeded); } } From 341658b55259084635b52983245800deff8d561d Mon Sep 17 00:00:00 2001 From: JPVenson Date: Wed, 1 Feb 2023 22:42:10 +0100 Subject: [PATCH 2/8] Update CleanupCollectionPathsTask.cs Removed code smell and switched to non creation for non existing collection folder --- .../ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs index 8e9270a125..7519af5b0d 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs @@ -65,16 +65,16 @@ public class CleanupCollectionPathsTask : IScheduledTask /// public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { - var collectionsFolder = await _collectionManager.GetCollectionsFolder(true).ConfigureAwait(false); + var collectionsFolder = await _collectionManager.GetCollectionsFolder(false).ConfigureAwait(false); if (collectionsFolder is null) { _logger.LogInformation("There is no collection folder to be found."); return; } - var collections = collectionsFolder.Children.OfType() - .ToArray(); + var collections = collectionsFolder.Children.OfType().ToArray(); _logger.LogTrace("Found {CollectionLength} Boxsets.", collections.Length); + for (var index = 0; index < collections.Length; index++) { var collection = collections[index]; @@ -84,7 +84,7 @@ public class CleanupCollectionPathsTask : IScheduledTask { if (!File.Exists(collectionLinkedChild.Path)) { - _logger.LogInformation("Item in boxset {0} cannot be found at {1}.", collection.Name, collectionLinkedChild.Path); + _logger.LogInformation("Item in boxset {CollectionName} cannot be found at {ItemPath}.", collection.Name, collectionLinkedChild.Path); itemsToRemove.Add(collectionLinkedChild); } } @@ -113,6 +113,5 @@ public class CleanupCollectionPathsTask : IScheduledTask public IEnumerable GetDefaultTriggers() { return new[] { new TaskTriggerInfo() { Type = TaskTriggerInfo.TriggerStartup } }; - // return Enumerable.Empty(); } } From 0b71974054b4f520fa0ef3ead8f1b688ec2d1d74 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Bachmann Date: Wed, 1 Feb 2023 23:45:06 +0100 Subject: [PATCH 3/8] Fixed whitespace --- .../ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs index 7519af5b0d..e1be43b9b2 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs @@ -74,7 +74,7 @@ public class CleanupCollectionPathsTask : IScheduledTask var collections = collectionsFolder.Children.OfType().ToArray(); _logger.LogTrace("Found {CollectionLength} Boxsets.", collections.Length); - + for (var index = 0; index < collections.Length; index++) { var collection = collections[index]; From 2a4cc4d942828886eb0c10389e602d67155aeca4 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Bachmann Date: Sun, 5 Feb 2023 21:08:08 +0200 Subject: [PATCH 4/8] Updated logging level and formatting --- .../Tasks/CleanupCollectionPathsTask.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs index e1be43b9b2..617fd687a3 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Emby.Server.Implementations.Collections; using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -68,30 +67,30 @@ public class CleanupCollectionPathsTask : IScheduledTask var collectionsFolder = await _collectionManager.GetCollectionsFolder(false).ConfigureAwait(false); if (collectionsFolder is null) { - _logger.LogInformation("There is no collection folder to be found."); + _logger.LogDebug("There is no collection folder to be found"); return; } var collections = collectionsFolder.Children.OfType().ToArray(); - _logger.LogTrace("Found {CollectionLength} Boxsets.", collections.Length); + _logger.LogTrace("Found {CollectionLength} Boxsets", collections.Length); for (var index = 0; index < collections.Length; index++) { var collection = collections[index]; - _logger.LogTrace("Check Boxset {CollectionName}.", collection.Name); + _logger.LogDebug("Check Boxset {CollectionName}", collection.Name); var itemsToRemove = new List(); foreach (var collectionLinkedChild in collection.LinkedChildren.ToArray()) { if (!File.Exists(collectionLinkedChild.Path)) { - _logger.LogInformation("Item in boxset {CollectionName} cannot be found at {ItemPath}.", collection.Name, collectionLinkedChild.Path); + _logger.LogInformation("Item in boxset {CollectionName} cannot be found at {ItemPath}", collection.Name, collectionLinkedChild.Path); itemsToRemove.Add(collectionLinkedChild); } } if (itemsToRemove.Any()) { - _logger.LogTrace("Update Boxset {CollectionName}.", collection.Name); + _logger.LogDebug("Update Boxset {CollectionName}", collection.Name); collection.LinkedChildren = collection.LinkedChildren.Except(itemsToRemove).ToArray(); await collection.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, cancellationToken) .ConfigureAwait(false); From 0ed4fd5759156dd12b0de749d5c452972f8d9fb8 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Bachmann Date: Sun, 5 Feb 2023 21:38:50 +0200 Subject: [PATCH 5/8] Changed LogTrace to LogDebug --- .../ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs index 617fd687a3..83e07478d2 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs @@ -72,7 +72,7 @@ public class CleanupCollectionPathsTask : IScheduledTask } var collections = collectionsFolder.Children.OfType().ToArray(); - _logger.LogTrace("Found {CollectionLength} Boxsets", collections.Length); + _logger.LogDebug("Found {CollectionLength} Boxsets", collections.Length); for (var index = 0; index < collections.Length; index++) { From 8b6fca59a1129c161e0b2ca44813921df20771b5 Mon Sep 17 00:00:00 2001 From: JPVenson Date: Tue, 2 May 2023 14:26:55 +0200 Subject: [PATCH 6/8] Update Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs Co-authored-by: Cody Robibero --- .../ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs index 83e07478d2..989c37242e 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs @@ -79,7 +79,7 @@ public class CleanupCollectionPathsTask : IScheduledTask var collection = collections[index]; _logger.LogDebug("Check Boxset {CollectionName}", collection.Name); var itemsToRemove = new List(); - foreach (var collectionLinkedChild in collection.LinkedChildren.ToArray()) + foreach (var collectionLinkedChild in collection.LinkedChildren) { if (!File.Exists(collectionLinkedChild.Path)) { From 0f60ec3013a4b1c776513fd92dc3829897b78db7 Mon Sep 17 00:00:00 2001 From: JPVenson Date: Tue, 27 Jun 2023 16:05:07 +0200 Subject: [PATCH 7/8] Update Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs Co-authored-by: Bond-009 --- .../ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs index 989c37242e..f8b044d46f 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs @@ -88,7 +88,7 @@ public class CleanupCollectionPathsTask : IScheduledTask } } - if (itemsToRemove.Any()) + if (itemsToRemove.Count != 0) { _logger.LogDebug("Update Boxset {CollectionName}", collection.Name); collection.LinkedChildren = collection.LinkedChildren.Except(itemsToRemove).ToArray(); From cc82ca189fcbd068c34c0d1c38a67d2332a96d44 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Tue, 27 Jun 2023 21:19:15 -0600 Subject: [PATCH 8/8] suggestions from review --- .../ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs index f8b044d46f..f78fc6f970 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionPathsTask.cs @@ -74,11 +74,12 @@ public class CleanupCollectionPathsTask : IScheduledTask var collections = collectionsFolder.Children.OfType().ToArray(); _logger.LogDebug("Found {CollectionLength} Boxsets", collections.Length); + var itemsToRemove = new List(); for (var index = 0; index < collections.Length; index++) { var collection = collections[index]; _logger.LogDebug("Check Boxset {CollectionName}", collection.Name); - var itemsToRemove = new List(); + foreach (var collectionLinkedChild in collection.LinkedChildren) { if (!File.Exists(collectionLinkedChild.Path)) @@ -102,6 +103,8 @@ public class CleanupCollectionPathsTask : IScheduledTask ForceSave = true }, RefreshPriority.High); + + itemsToRemove.Clear(); } progress.Report(100D / collections.Length * (index + 1));