mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-08 08:48:48 +01:00
Merge pull request #16941 from Shadowghost/fix-external-data-pruning
Fix external data pruning on item deletion
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Chapters;
|
||||
@@ -52,26 +51,33 @@ public class ExternalDataManager : IExternalDataManager
|
||||
/// <inheritdoc/>
|
||||
public async Task DeleteExternalItemDataAsync(BaseItem item, CancellationToken cancellationToken)
|
||||
{
|
||||
var validPaths = _pathManager.GetExtractedDataPaths(item).Where(Directory.Exists).ToList();
|
||||
var itemId = item.Id;
|
||||
if (validPaths.Count > 0)
|
||||
{
|
||||
foreach (var path in validPaths)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(path, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning("Unable to prune external item data at {Path}: {Exception}", path, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
DeleteExternalItemFiles(item);
|
||||
|
||||
var itemId = item.Id;
|
||||
await _keyframeManager.DeleteKeyframeDataAsync(itemId, cancellationToken).ConfigureAwait(false);
|
||||
await _mediaSegmentManager.DeleteSegmentsAsync(itemId, cancellationToken).ConfigureAwait(false);
|
||||
await _trickplayManager.DeleteTrickplayDataAsync(itemId, cancellationToken).ConfigureAwait(false);
|
||||
await _chapterManager.DeleteChapterDataAsync(itemId, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void DeleteExternalItemFiles(BaseItem item)
|
||||
{
|
||||
foreach (var path in _pathManager.GetExtractedDataPaths(item))
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(path, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning("Unable to prune external item data at {Path}: {Exception}", path, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ namespace Emby.Server.Implementations.Library
|
||||
private readonly FastConcurrentLru<Guid, BaseItem> _cache;
|
||||
private readonly DotIgnoreIgnoreRule _dotIgnoreIgnoreRule;
|
||||
private readonly IMediaStreamRepository _mediaStreamRepository;
|
||||
private readonly Lazy<IExternalDataManager> _externalDataManagerFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The _root folder sync lock.
|
||||
@@ -132,6 +133,7 @@ namespace Emby.Server.Implementations.Library
|
||||
/// <param name="pathManager">The path manager.</param>
|
||||
/// <param name="dotIgnoreIgnoreRule">The .ignore rule handler.</param>
|
||||
/// <param name="mediaStreamRepository">The media stream repository.</param>
|
||||
/// <param name="externalDataManagerFactory">The external data manager (lazy, to break the DI cycle through ChapterManager).</param>
|
||||
public LibraryManager(
|
||||
IServerApplicationHost appHost,
|
||||
ILoggerFactory loggerFactory,
|
||||
@@ -155,7 +157,8 @@ namespace Emby.Server.Implementations.Library
|
||||
IPeopleRepository peopleRepository,
|
||||
IPathManager pathManager,
|
||||
DotIgnoreIgnoreRule dotIgnoreIgnoreRule,
|
||||
IMediaStreamRepository mediaStreamRepository)
|
||||
IMediaStreamRepository mediaStreamRepository,
|
||||
Lazy<IExternalDataManager> externalDataManagerFactory)
|
||||
{
|
||||
_appHost = appHost;
|
||||
_logger = loggerFactory.CreateLogger<LibraryManager>();
|
||||
@@ -186,6 +189,7 @@ namespace Emby.Server.Implementations.Library
|
||||
_configurationManager.ConfigurationUpdated += ConfigurationUpdated;
|
||||
|
||||
_mediaStreamRepository = mediaStreamRepository;
|
||||
_externalDataManagerFactory = externalDataManagerFactory;
|
||||
|
||||
RecordConfigurationValues(_configurationManager.Configuration);
|
||||
}
|
||||
@@ -396,6 +400,12 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
}
|
||||
|
||||
var externalDataManager = _externalDataManagerFactory.Value;
|
||||
foreach (var (item, _, _) in pathMaps)
|
||||
{
|
||||
externalDataManager.DeleteExternalItemFiles(item);
|
||||
}
|
||||
|
||||
_persistenceService.DeleteItem([.. pathMaps.Select(f => f.Item.Id)]);
|
||||
}
|
||||
|
||||
@@ -576,6 +586,13 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
item.SetParent(null);
|
||||
|
||||
var externalDataManager = _externalDataManagerFactory.Value;
|
||||
externalDataManager.DeleteExternalItemFiles(item);
|
||||
foreach (var child in children)
|
||||
{
|
||||
externalDataManager.DeleteExternalItemFiles(child);
|
||||
}
|
||||
|
||||
_persistenceService.DeleteItem([item.Id, .. children.Select(f => f.Id)]);
|
||||
_cache.TryRemove(item.Id, out _);
|
||||
foreach (var child in children)
|
||||
|
||||
@@ -121,7 +121,11 @@ public class PathManager : IPathManager
|
||||
}
|
||||
|
||||
paths.Add(GetTrickplayDirectory(item, false));
|
||||
paths.Add(GetTrickplayDirectory(item, true));
|
||||
if (!string.IsNullOrEmpty(item.Path))
|
||||
{
|
||||
paths.Add(GetTrickplayDirectory(item, true));
|
||||
}
|
||||
|
||||
paths.Add(GetChapterImageFolderPath(item));
|
||||
|
||||
return paths;
|
||||
|
||||
Reference in New Issue
Block a user