aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/ScheduledTasks/Tasks
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/ScheduledTasks/Tasks')
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs150
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs240
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs101
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionAndPlaylistPathsTask.cs21
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupUserDataTask.cs77
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs203
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs130
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs171
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs9
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs125
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs94
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs164
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs83
13 files changed, 819 insertions, 749 deletions
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs
index 031d14776..e912e9f01 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs
@@ -76,93 +76,111 @@ public partial class AudioNormalizationTask : IScheduledTask
/// <inheritdoc />
public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
{
- foreach (var library in _libraryManager.RootFolder.Children)
+ var numComplete = 0;
+ var libraries = _libraryManager.RootFolder.Children.Where(library => _libraryManager.GetLibraryOptions(library).EnableLUFSScan).ToArray();
+ double percent = 0;
+
+ foreach (var library in libraries)
{
- var libraryOptions = _libraryManager.GetLibraryOptions(library);
- if (!libraryOptions.EnableLUFSScan)
- {
- continue;
- }
+ var albums = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = [BaseItemKind.MusicAlbum], Parent = library, Recursive = true });
- // Album gain
- var albums = _libraryManager.GetItemList(new InternalItemsQuery
- {
- IncludeItemTypes = [BaseItemKind.MusicAlbum],
- Parent = library,
- Recursive = true
- });
+ double nextPercent = numComplete + 1;
+ nextPercent /= libraries.Length;
+ nextPercent -= percent;
+ // Split the progress for this single library into two halves: album gain and track gain.
+ // The first half will be for album gain, the second half for track gain.
+ nextPercent /= 2;
+ var albumComplete = 0;
foreach (var a in albums)
{
- if (a.NormalizationGain.HasValue || a.LUFS.HasValue)
+ if (!a.NormalizationGain.HasValue && !a.LUFS.HasValue)
{
- continue;
+ // Album gain
+ var albumTracks = ((MusicAlbum)a).Tracks.Where(x => x.IsFileProtocol).ToList();
+
+ // Skip albums that don't have multiple tracks, album gain is useless here
+ if (albumTracks.Count > 1)
+ {
+ _logger.LogInformation("Calculating LUFS for album: {Album} with id: {Id}", a.Name, a.Id);
+ var tempDir = _applicationPaths.TempDirectory;
+ Directory.CreateDirectory(tempDir);
+ var tempFile = Path.Join(tempDir, a.Id + ".concat");
+ var inputLines = albumTracks.Select(x => string.Format(CultureInfo.InvariantCulture, "file '{0}'", x.Path.Replace("'", @"'\''", StringComparison.Ordinal)));
+ await File.WriteAllLinesAsync(tempFile, inputLines, cancellationToken).ConfigureAwait(false);
+ try
+ {
+ a.LUFS = await CalculateLUFSAsync(
+ string.Format(CultureInfo.InvariantCulture, "-f concat -safe 0 -i \"{0}\"", tempFile),
+ OperatingSystem.IsWindows(), // Wait for process to exit on Windows before we try deleting the concat file
+ cancellationToken).ConfigureAwait(false);
+ }
+ finally
+ {
+ File.Delete(tempFile);
+ }
+ }
}
- // Skip albums that don't have multiple tracks, album gain is useless here
- var albumTracks = ((MusicAlbum)a).Tracks.Where(x => x.IsFileProtocol).ToList();
- if (albumTracks.Count <= 1)
- {
- continue;
- }
+ // Update sub-progress for album gain
+ albumComplete++;
+ double albumPercent = albumComplete;
+ albumPercent /= albums.Count;
- _logger.LogInformation("Calculating LUFS for album: {Album} with id: {Id}", a.Name, a.Id);
- var tempDir = _applicationPaths.TempDirectory;
- Directory.CreateDirectory(tempDir);
- var tempFile = Path.Join(tempDir, a.Id + ".concat");
- var inputLines = albumTracks.Select(x => string.Format(CultureInfo.InvariantCulture, "file '{0}'", x.Path.Replace("'", @"'\''", StringComparison.Ordinal)));
- await File.WriteAllLinesAsync(tempFile, inputLines, cancellationToken).ConfigureAwait(false);
- try
- {
- a.LUFS = await CalculateLUFSAsync(
- string.Format(CultureInfo.InvariantCulture, "-f concat -safe 0 -i \"{0}\"", tempFile),
- cancellationToken).ConfigureAwait(false);
- }
- finally
- {
- File.Delete(tempFile);
- }
+ progress.Report(100 * (percent + (albumPercent * nextPercent)));
}
+ // Update progress to start at the track gain percent calculation
+ percent += nextPercent;
+
_itemRepository.SaveItems(albums, cancellationToken);
// Track gain
- var tracks = _libraryManager.GetItemList(new InternalItemsQuery
- {
- MediaTypes = [MediaType.Audio],
- IncludeItemTypes = [BaseItemKind.Audio],
- Parent = library,
- Recursive = true
- });
+ var tracks = _libraryManager.GetItemList(new InternalItemsQuery { MediaTypes = [MediaType.Audio], IncludeItemTypes = [BaseItemKind.Audio], Parent = library, Recursive = true });
+ var tracksComplete = 0;
foreach (var t in tracks)
{
- if (t.NormalizationGain.HasValue || t.LUFS.HasValue || !t.IsFileProtocol)
+ if (!t.NormalizationGain.HasValue && !t.LUFS.HasValue && t.IsFileProtocol)
{
- continue;
+ t.LUFS = await CalculateLUFSAsync(
+ string.Format(CultureInfo.InvariantCulture, "-i \"{0}\"", t.Path.Replace("\"", "\\\"", StringComparison.Ordinal)),
+ false,
+ cancellationToken).ConfigureAwait(false);
}
- t.LUFS = await CalculateLUFSAsync(string.Format(CultureInfo.InvariantCulture, "-i \"{0}\"", t.Path.Replace("\"", "\\\"", StringComparison.Ordinal)), cancellationToken).ConfigureAwait(false);
+ // Update sub-progress for track gain
+ tracksComplete++;
+ double trackPercent = tracksComplete;
+ trackPercent /= tracks.Count;
+
+ progress.Report(100 * (percent + (trackPercent * nextPercent)));
}
_itemRepository.SaveItems(tracks, cancellationToken);
+
+ // Update progress
+ numComplete++;
+ percent = numComplete;
+ percent /= libraries.Length;
+
+ progress.Report(100 * percent);
}
+
+ progress.Report(100.0);
}
/// <inheritdoc />
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
- return
- [
- new TaskTriggerInfo
- {
- Type = TaskTriggerInfoType.IntervalTrigger,
- IntervalTicks = TimeSpan.FromHours(24).Ticks
- }
- ];
+ yield return new TaskTriggerInfo
+ {
+ Type = TaskTriggerInfoType.IntervalTrigger,
+ IntervalTicks = TimeSpan.FromHours(24).Ticks
+ };
}
- private async Task<float?> CalculateLUFSAsync(string inputArgs, CancellationToken cancellationToken)
+ private async Task<float?> CalculateLUFSAsync(string inputArgs, bool waitForExit, CancellationToken cancellationToken)
{
var args = $"-hide_banner {inputArgs} -af ebur128=framelog=verbose -f null -";
@@ -189,18 +207,28 @@ public partial class AudioNormalizationTask : IScheduledTask
}
using var reader = process.StandardError;
- await foreach (var line in reader.ReadAllLinesAsync(cancellationToken))
+ float? lufs = null;
+ await foreach (var line in reader.ReadAllLinesAsync(cancellationToken).ConfigureAwait(false))
{
Match match = LUFSRegex().Match(line);
-
if (match.Success)
{
- return float.Parse(match.Groups[1].ValueSpan, CultureInfo.InvariantCulture.NumberFormat);
+ lufs = float.Parse(match.Groups[1].ValueSpan, CultureInfo.InvariantCulture.NumberFormat);
+ break;
}
}
- _logger.LogError("Failed to find LUFS value in output");
- return null;
+ if (lufs is null)
+ {
+ _logger.LogError("Failed to find LUFS value in output");
+ }
+
+ if (waitForExit)
+ {
+ await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
+ }
+
+ return lufs;
}
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
index 563e90fbe..f81309560 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
@@ -11,171 +11,157 @@ using MediaBrowser.Controller.Chapters;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.MediaEncoding;
-using MediaBrowser.Controller.Persistence;
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
+namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
+
+/// <summary>
+/// Class ChapterImagesTask.
+/// </summary>
+public class ChapterImagesTask : IScheduledTask
{
+ private readonly ILogger<ChapterImagesTask> _logger;
+ private readonly ILibraryManager _libraryManager;
+ private readonly IApplicationPaths _appPaths;
+ private readonly IChapterManager _chapterManager;
+ private readonly IFileSystem _fileSystem;
+ private readonly ILocalizationManager _localization;
+
/// <summary>
- /// Class ChapterImagesTask.
+ /// Initializes a new instance of the <see cref="ChapterImagesTask" /> class.
/// </summary>
- public class ChapterImagesTask : IScheduledTask
+ /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
+ /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
+ /// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
+ /// <param name="chapterManager">Instance of the <see cref="IChapterManager"/> interface.</param>
+ /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
+ /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
+ public ChapterImagesTask(
+ ILogger<ChapterImagesTask> logger,
+ ILibraryManager libraryManager,
+ IApplicationPaths appPaths,
+ IChapterManager chapterManager,
+ IFileSystem fileSystem,
+ ILocalizationManager localization)
{
- private readonly ILogger<ChapterImagesTask> _logger;
- private readonly ILibraryManager _libraryManager;
- private readonly IItemRepository _itemRepo;
- private readonly IApplicationPaths _appPaths;
- private readonly IEncodingManager _encodingManager;
- private readonly IFileSystem _fileSystem;
- private readonly ILocalizationManager _localization;
- private readonly IChapterRepository _chapterRepository;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ChapterImagesTask" /> class.
- /// </summary>
- /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
- /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
- /// <param name="itemRepo">Instance of the <see cref="IItemRepository"/> interface.</param>
- /// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
- /// <param name="encodingManager">Instance of the <see cref="IEncodingManager"/> interface.</param>
- /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
- /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
- /// <param name="chapterRepository">Instance of the <see cref="IChapterRepository"/> interface.</param>
- public ChapterImagesTask(
- ILogger<ChapterImagesTask> logger,
- ILibraryManager libraryManager,
- IItemRepository itemRepo,
- IApplicationPaths appPaths,
- IEncodingManager encodingManager,
- IFileSystem fileSystem,
- ILocalizationManager localization,
- IChapterRepository chapterRepository)
- {
- _logger = logger;
- _libraryManager = libraryManager;
- _itemRepo = itemRepo;
- _appPaths = appPaths;
- _encodingManager = encodingManager;
- _fileSystem = fileSystem;
- _localization = localization;
- _chapterRepository = chapterRepository;
- }
+ _logger = logger;
+ _libraryManager = libraryManager;
+ _appPaths = appPaths;
+ _chapterManager = chapterManager;
+ _fileSystem = fileSystem;
+ _localization = localization;
+ }
- /// <inheritdoc />
- public string Name => _localization.GetLocalizedString("TaskRefreshChapterImages");
+ /// <inheritdoc />
+ public string Name => _localization.GetLocalizedString("TaskRefreshChapterImages");
- /// <inheritdoc />
- public string Description => _localization.GetLocalizedString("TaskRefreshChapterImagesDescription");
+ /// <inheritdoc />
+ public string Description => _localization.GetLocalizedString("TaskRefreshChapterImagesDescription");
- /// <inheritdoc />
- public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
+ /// <inheritdoc />
+ public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
- /// <inheritdoc />
- public string Key => "RefreshChapterImages";
+ /// <inheritdoc />
+ public string Key => "RefreshChapterImages";
- /// <inheritdoc />
- public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ /// <inheritdoc />
+ public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ {
+ yield return new TaskTriggerInfo
{
- return
- [
- new TaskTriggerInfo
- {
- Type = TaskTriggerInfoType.DailyTrigger,
- TimeOfDayTicks = TimeSpan.FromHours(2).Ticks,
- MaxRuntimeTicks = TimeSpan.FromHours(4).Ticks
- }
- ];
- }
+ Type = TaskTriggerInfoType.DailyTrigger,
+ TimeOfDayTicks = TimeSpan.FromHours(2).Ticks,
+ MaxRuntimeTicks = TimeSpan.FromHours(4).Ticks
+ };
+ }
- /// <inheritdoc />
- public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ /// <inheritdoc />
+ public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ var videos = _libraryManager.GetItemList(new InternalItemsQuery
{
- var videos = _libraryManager.GetItemList(new InternalItemsQuery
+ MediaTypes = [MediaType.Video],
+ IsFolder = false,
+ Recursive = true,
+ DtoOptions = new DtoOptions(false)
{
- MediaTypes = [MediaType.Video],
- IsFolder = false,
- Recursive = true,
- DtoOptions = new DtoOptions(false)
- {
- EnableImages = false
- },
- SourceTypes = [SourceType.Library],
- IsVirtualItem = false
- })
- .OfType<Video>()
- .ToList();
+ EnableImages = false
+ },
+ SourceTypes = [SourceType.Library],
+ IsVirtualItem = false
+ })
+ .OfType<Video>()
+ .ToList();
- var numComplete = 0;
+ var numComplete = 0;
- var failHistoryPath = Path.Combine(_appPaths.CachePath, "chapter-failures.txt");
+ var failHistoryPath = Path.Combine(_appPaths.CachePath, "chapter-failures.txt");
- List<string> previouslyFailedImages;
+ List<string> previouslyFailedImages;
- if (File.Exists(failHistoryPath))
+ if (File.Exists(failHistoryPath))
+ {
+ try
{
- try
- {
- previouslyFailedImages = (await File.ReadAllTextAsync(failHistoryPath, cancellationToken).ConfigureAwait(false))
- .Split('|', StringSplitOptions.RemoveEmptyEntries)
- .ToList();
- }
- catch (IOException)
- {
- previouslyFailedImages = new List<string>();
- }
+ previouslyFailedImages = (await File.ReadAllTextAsync(failHistoryPath, cancellationToken).ConfigureAwait(false))
+ .Split('|', StringSplitOptions.RemoveEmptyEntries)
+ .ToList();
}
- else
+ catch (IOException)
{
- previouslyFailedImages = new List<string>();
+ previouslyFailedImages = [];
}
+ }
+ else
+ {
+ previouslyFailedImages = [];
+ }
- var directoryService = new DirectoryService(_fileSystem);
-
- foreach (var video in videos)
- {
- cancellationToken.ThrowIfCancellationRequested();
+ var directoryService = new DirectoryService(_fileSystem);
- var key = video.Path + video.DateModified.Ticks;
+ foreach (var video in videos)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
- var extract = !previouslyFailedImages.Contains(key, StringComparison.OrdinalIgnoreCase);
+ var key = video.Path + video.DateModified.Ticks;
- try
- {
- var chapters = _chapterRepository.GetChapters(video.Id);
+ var extract = !previouslyFailedImages.Contains(key, StringComparison.OrdinalIgnoreCase);
- var success = await _encodingManager.RefreshChapterImages(video, directoryService, chapters, extract, true, cancellationToken).ConfigureAwait(false);
+ try
+ {
+ var chapters = _chapterManager.GetChapters(video.Id);
- if (!success)
- {
- previouslyFailedImages.Add(key);
+ var success = await _chapterManager.RefreshChapterImages(video, directoryService, chapters, extract, true, cancellationToken).ConfigureAwait(false);
- var parentPath = Path.GetDirectoryName(failHistoryPath);
- if (parentPath is not null)
- {
- Directory.CreateDirectory(parentPath);
- }
+ if (!success)
+ {
+ previouslyFailedImages.Add(key);
- string text = string.Join('|', previouslyFailedImages);
- await File.WriteAllTextAsync(failHistoryPath, text, cancellationToken).ConfigureAwait(false);
+ var parentPath = Path.GetDirectoryName(failHistoryPath);
+ if (parentPath is not null)
+ {
+ Directory.CreateDirectory(parentPath);
}
- numComplete++;
- double percent = numComplete;
- percent /= videos.Count;
-
- progress.Report(100 * percent);
- }
- catch (ObjectDisposedException ex)
- {
- // TODO Investigate and properly fix.
- _logger.LogError(ex, "Object Disposed");
- break;
+ string text = string.Join('|', previouslyFailedImages);
+ await File.WriteAllTextAsync(failHistoryPath, text, cancellationToken).ConfigureAwait(false);
}
+
+ numComplete++;
+ double percent = numComplete;
+ percent /= videos.Count;
+
+ progress.Report(100 * percent);
+ }
+ catch (ObjectDisposedException ex)
+ {
+ // TODO Investigate and properly fix.
+ _logger.LogError(ex, "Object Disposed");
+ break;
}
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs
index fe1832165..1621bbaa1 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs
@@ -7,71 +7,70 @@ using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Tasks;
-namespace Emby.Server.Implementations.ScheduledTasks.Tasks
+namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
+
+/// <summary>
+/// Deletes old activity log entries.
+/// </summary>
+public class CleanActivityLogTask : IScheduledTask, IConfigurableScheduledTask
{
+ private readonly ILocalizationManager _localization;
+ private readonly IActivityManager _activityManager;
+ private readonly IServerConfigurationManager _serverConfigurationManager;
+
/// <summary>
- /// Deletes old activity log entries.
+ /// Initializes a new instance of the <see cref="CleanActivityLogTask"/> class.
/// </summary>
- public class CleanActivityLogTask : IScheduledTask, IConfigurableScheduledTask
+ /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
+ /// <param name="activityManager">Instance of the <see cref="IActivityManager"/> interface.</param>
+ /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
+ public CleanActivityLogTask(
+ ILocalizationManager localization,
+ IActivityManager activityManager,
+ IServerConfigurationManager serverConfigurationManager)
{
- private readonly ILocalizationManager _localization;
- private readonly IActivityManager _activityManager;
- private readonly IServerConfigurationManager _serverConfigurationManager;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="CleanActivityLogTask"/> class.
- /// </summary>
- /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
- /// <param name="activityManager">Instance of the <see cref="IActivityManager"/> interface.</param>
- /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
- public CleanActivityLogTask(
- ILocalizationManager localization,
- IActivityManager activityManager,
- IServerConfigurationManager serverConfigurationManager)
- {
- _localization = localization;
- _activityManager = activityManager;
- _serverConfigurationManager = serverConfigurationManager;
- }
+ _localization = localization;
+ _activityManager = activityManager;
+ _serverConfigurationManager = serverConfigurationManager;
+ }
- /// <inheritdoc />
- public string Name => _localization.GetLocalizedString("TaskCleanActivityLog");
+ /// <inheritdoc />
+ public string Name => _localization.GetLocalizedString("TaskCleanActivityLog");
- /// <inheritdoc />
- public string Key => "CleanActivityLog";
+ /// <inheritdoc />
+ public string Key => "CleanActivityLog";
- /// <inheritdoc />
- public string Description => _localization.GetLocalizedString("TaskCleanActivityLogDescription");
+ /// <inheritdoc />
+ public string Description => _localization.GetLocalizedString("TaskCleanActivityLogDescription");
- /// <inheritdoc />
- public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
+ /// <inheritdoc />
+ public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
- /// <inheritdoc />
- public bool IsHidden => false;
+ /// <inheritdoc />
+ public bool IsHidden => false;
- /// <inheritdoc />
- public bool IsEnabled => true;
+ /// <inheritdoc />
+ public bool IsEnabled => true;
- /// <inheritdoc />
- public bool IsLogged => true;
+ /// <inheritdoc />
+ public bool IsLogged => true;
- /// <inheritdoc />
- public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ /// <inheritdoc />
+ public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ var retentionDays = _serverConfigurationManager.Configuration.ActivityLogRetentionDays;
+ if (!retentionDays.HasValue || retentionDays < 0)
{
- var retentionDays = _serverConfigurationManager.Configuration.ActivityLogRetentionDays;
- if (!retentionDays.HasValue || retentionDays < 0)
- {
- throw new InvalidOperationException($"Activity Log Retention days must be at least 0. Currently: {retentionDays}");
- }
-
- var startDate = DateTime.UtcNow.AddDays(-retentionDays.Value);
- return _activityManager.CleanAsync(startDate);
+ throw new InvalidOperationException($"Activity Log Retention days must be at least 0. Currently: {retentionDays}");
}
- /// <inheritdoc />
- public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
- {
- return [];
- }
+ var startDate = DateTime.UtcNow.AddDays(-retentionDays.Value);
+ return _activityManager.CleanAsync(startDate);
+ }
+
+ /// <inheritdoc />
+ public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ {
+ return [];
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionAndPlaylistPathsTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionAndPlaylistPathsTask.cs
index 316e4a8f0..7f68f7701 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionAndPlaylistPathsTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionAndPlaylistPathsTask.cs
@@ -27,7 +27,6 @@ public class CleanupCollectionAndPlaylistPathsTask : IScheduledTask
private readonly IPlaylistManager _playlistManager;
private readonly ILogger<CleanupCollectionAndPlaylistPathsTask> _logger;
private readonly IProviderManager _providerManager;
- private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="CleanupCollectionAndPlaylistPathsTask"/> class.
@@ -37,21 +36,18 @@ public class CleanupCollectionAndPlaylistPathsTask : IScheduledTask
/// <param name="playlistManager">Instance of the <see cref="IPlaylistManager"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
/// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
- /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
public CleanupCollectionAndPlaylistPathsTask(
ILocalizationManager localization,
ICollectionManager collectionManager,
IPlaylistManager playlistManager,
ILogger<CleanupCollectionAndPlaylistPathsTask> logger,
- IProviderManager providerManager,
- IFileSystem fileSystem)
+ IProviderManager providerManager)
{
_localization = localization;
_collectionManager = collectionManager;
_playlistManager = playlistManager;
_logger = logger;
_providerManager = providerManager;
- _fileSystem = fileSystem;
}
/// <inheritdoc />
@@ -84,7 +80,7 @@ public class CleanupCollectionAndPlaylistPathsTask : IScheduledTask
var collection = collections[index];
_logger.LogDebug("Checking boxset {CollectionName}", collection.Name);
- CleanupLinkedChildren(collection, cancellationToken);
+ await CleanupLinkedChildrenAsync(collection, cancellationToken).ConfigureAwait(false);
progress.Report(50D / collections.Length * (index + 1));
}
}
@@ -104,12 +100,12 @@ public class CleanupCollectionAndPlaylistPathsTask : IScheduledTask
var playlist = playlists[index];
_logger.LogDebug("Checking playlist {PlaylistName}", playlist.Name);
- CleanupLinkedChildren(playlist, cancellationToken);
+ await CleanupLinkedChildrenAsync(playlist, cancellationToken).ConfigureAwait(false);
progress.Report(50D / playlists.Length * (index + 1));
}
}
- private void CleanupLinkedChildren<T>(T folder, CancellationToken cancellationToken)
+ private async Task CleanupLinkedChildrenAsync<T>(T folder, CancellationToken cancellationToken)
where T : Folder
{
List<LinkedChild>? itemsToRemove = null;
@@ -127,14 +123,17 @@ public class CleanupCollectionAndPlaylistPathsTask : IScheduledTask
{
_logger.LogDebug("Updating {FolderName}", folder.Name);
folder.LinkedChildren = folder.LinkedChildren.Except(itemsToRemove).ToArray();
- _providerManager.SaveMetadataAsync(folder, ItemUpdateType.MetadataEdit);
- folder.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, cancellationToken);
+ await _providerManager.SaveMetadataAsync(folder, ItemUpdateType.MetadataEdit).ConfigureAwait(false);
+ await folder.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
}
}
/// <inheritdoc />
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
- return [new TaskTriggerInfo() { Type = TaskTriggerInfoType.StartupTrigger }];
+ yield return new TaskTriggerInfo
+ {
+ Type = TaskTriggerInfoType.StartupTrigger,
+ };
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupUserDataTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupUserDataTask.cs
new file mode 100644
index 000000000..4156050eb
--- /dev/null
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupUserDataTask.cs
@@ -0,0 +1,77 @@
+#pragma warning disable RS0030 // Do not use banned APIs
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Database.Implementations;
+using Jellyfin.Server.Implementations.Item;
+using MediaBrowser.Model.Globalization;
+using MediaBrowser.Model.Tasks;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+
+namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
+
+/// <summary>
+/// Task to clean up any detached userdata from the database.
+/// </summary>
+public class CleanupUserDataTask : IScheduledTask
+{
+ private readonly ILocalizationManager _localization;
+ private readonly IDbContextFactory<JellyfinDbContext> _dbProvider;
+ private readonly ILogger<CleanupUserDataTask> _logger;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CleanupUserDataTask"/> class.
+ /// </summary>
+ /// <param name="localization">The localisation Provider.</param>
+ /// <param name="dbProvider">The DB context factory.</param>
+ /// <param name="logger">A logger.</param>
+ public CleanupUserDataTask(ILocalizationManager localization, IDbContextFactory<JellyfinDbContext> dbProvider, ILogger<CleanupUserDataTask> logger)
+ {
+ _localization = localization;
+ _dbProvider = dbProvider;
+ _logger = logger;
+ }
+
+ /// <inheritdoc />
+ public string Name => _localization.GetLocalizedString("CleanupUserDataTask");
+
+ /// <inheritdoc />
+ public string Description => _localization.GetLocalizedString("CleanupUserDataTaskDescription");
+
+ /// <inheritdoc />
+ public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
+
+ /// <inheritdoc />
+ public string Key => nameof(CleanupUserDataTask);
+
+ /// <inheritdoc/>
+ public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ const int LimitDays = 90;
+ var userDataDate = DateTime.UtcNow.AddDays(LimitDays * -1);
+ var dbContext = await _dbProvider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
+ await using (dbContext.ConfigureAwait(false))
+ {
+ var detachedUserData = dbContext.UserData.Where(e => e.ItemId == BaseItemRepository.PlaceholderId);
+ _logger.LogInformation("There are {NoDetached} detached UserData entries.", detachedUserData.Count());
+
+ detachedUserData = detachedUserData.Where(e => e.RetentionDate < userDataDate);
+
+ _logger.LogInformation("{NoDetached} are older then {Limit} days.", detachedUserData.Count(), LimitDays);
+
+ await detachedUserData.ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false);
+ }
+
+ progress.Report(100);
+ }
+
+ /// <inheritdoc/>
+ public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ {
+ yield break;
+ }
+}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
index ff295d9b7..0e77f0102 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
@@ -11,134 +11,133 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
-namespace Emby.Server.Implementations.ScheduledTasks.Tasks
+namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
+
+/// <summary>
+/// Deletes old cache files.
+/// </summary>
+public class DeleteCacheFileTask : IScheduledTask, IConfigurableScheduledTask
{
/// <summary>
- /// Deletes old cache files.
+ /// Gets or sets the application paths.
+ /// </summary>
+ /// <value>The application paths.</value>
+ private readonly IApplicationPaths _applicationPaths;
+ private readonly ILogger<DeleteCacheFileTask> _logger;
+ private readonly IFileSystem _fileSystem;
+ private readonly ILocalizationManager _localization;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
/// </summary>
- public class DeleteCacheFileTask : IScheduledTask, IConfigurableScheduledTask
+ /// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
+ /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
+ /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
+ /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
+ public DeleteCacheFileTask(
+ IApplicationPaths appPaths,
+ ILogger<DeleteCacheFileTask> logger,
+ IFileSystem fileSystem,
+ ILocalizationManager localization)
{
- /// <summary>
- /// Gets or sets the application paths.
- /// </summary>
- /// <value>The application paths.</value>
- private readonly IApplicationPaths _applicationPaths;
- private readonly ILogger<DeleteCacheFileTask> _logger;
- private readonly IFileSystem _fileSystem;
- private readonly ILocalizationManager _localization;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
- /// </summary>
- /// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
- /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
- /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
- /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
- public DeleteCacheFileTask(
- IApplicationPaths appPaths,
- ILogger<DeleteCacheFileTask> logger,
- IFileSystem fileSystem,
- ILocalizationManager localization)
- {
- _applicationPaths = appPaths;
- _logger = logger;
- _fileSystem = fileSystem;
- _localization = localization;
- }
+ _applicationPaths = appPaths;
+ _logger = logger;
+ _fileSystem = fileSystem;
+ _localization = localization;
+ }
- /// <inheritdoc />
- public string Name => _localization.GetLocalizedString("TaskCleanCache");
+ /// <inheritdoc />
+ public string Name => _localization.GetLocalizedString("TaskCleanCache");
- /// <inheritdoc />
- public string Description => _localization.GetLocalizedString("TaskCleanCacheDescription");
+ /// <inheritdoc />
+ public string Description => _localization.GetLocalizedString("TaskCleanCacheDescription");
- /// <inheritdoc />
- public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
+ /// <inheritdoc />
+ public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
- /// <inheritdoc />
- public string Key => "DeleteCacheFiles";
+ /// <inheritdoc />
+ public string Key => "DeleteCacheFiles";
- /// <inheritdoc />
- public bool IsHidden => false;
+ /// <inheritdoc />
+ public bool IsHidden => false;
- /// <inheritdoc />
- public bool IsEnabled => true;
+ /// <inheritdoc />
+ public bool IsEnabled => true;
- /// <inheritdoc />
- public bool IsLogged => true;
+ /// <inheritdoc />
+ public bool IsLogged => true;
- /// <inheritdoc />
- public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ /// <inheritdoc />
+ public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ {
+ yield return new TaskTriggerInfo
{
- return
- [
- // Every so often
- new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks }
- ];
- }
+ Type = TaskTriggerInfoType.IntervalTrigger,
+ IntervalTicks = TimeSpan.FromHours(24).Ticks
+ };
+ }
- /// <inheritdoc />
- public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ /// <inheritdoc />
+ public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ var minDateModified = DateTime.UtcNow.AddDays(-30);
+
+ try
+ {
+ DeleteCacheFilesFromDirectory(_applicationPaths.CachePath, minDateModified, progress, cancellationToken);
+ }
+ catch (DirectoryNotFoundException)
{
- var minDateModified = DateTime.UtcNow.AddDays(-30);
-
- try
- {
- DeleteCacheFilesFromDirectory(_applicationPaths.CachePath, minDateModified, progress, cancellationToken);
- }
- catch (DirectoryNotFoundException)
- {
- // No biggie here. Nothing to delete
- }
-
- progress.Report(90);
-
- minDateModified = DateTime.UtcNow.AddDays(-1);
-
- try
- {
- DeleteCacheFilesFromDirectory(_applicationPaths.TempDirectory, minDateModified, progress, cancellationToken);
- }
- catch (DirectoryNotFoundException)
- {
- // No biggie here. Nothing to delete
- }
-
- return Task.CompletedTask;
+ // No biggie here. Nothing to delete
}
- /// <summary>
- /// Deletes the cache files from directory with a last write time less than a given date.
- /// </summary>
- /// <param name="directory">The directory.</param>
- /// <param name="minDateModified">The min date modified.</param>
- /// <param name="progress">The progress.</param>
- /// <param name="cancellationToken">The task cancellation token.</param>
- private void DeleteCacheFilesFromDirectory(string directory, DateTime minDateModified, IProgress<double> progress, CancellationToken cancellationToken)
+ progress.Report(90);
+
+ minDateModified = DateTime.UtcNow.AddDays(-1);
+
+ try
{
- var filesToDelete = _fileSystem.GetFiles(directory, true)
- .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
- .ToList();
+ DeleteCacheFilesFromDirectory(_applicationPaths.TempDirectory, minDateModified, progress, cancellationToken);
+ }
+ catch (DirectoryNotFoundException)
+ {
+ // No biggie here. Nothing to delete
+ }
- var index = 0;
+ return Task.CompletedTask;
+ }
- foreach (var file in filesToDelete)
- {
- double percent = index;
- percent /= filesToDelete.Count;
+ /// <summary>
+ /// Deletes the cache files from directory with a last write time less than a given date.
+ /// </summary>
+ /// <param name="directory">The directory.</param>
+ /// <param name="minDateModified">The min date modified.</param>
+ /// <param name="progress">The progress.</param>
+ /// <param name="cancellationToken">The task cancellation token.</param>
+ private void DeleteCacheFilesFromDirectory(string directory, DateTime minDateModified, IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ var filesToDelete = _fileSystem.GetFiles(directory, true)
+ .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
+ .ToList();
- progress.Report(100 * percent);
+ var index = 0;
- cancellationToken.ThrowIfCancellationRequested();
+ foreach (var file in filesToDelete)
+ {
+ double percent = index;
+ percent /= filesToDelete.Count;
- FileSystemHelper.DeleteFile(_fileSystem, file.FullName, _logger);
+ progress.Report(100 * percent);
- index++;
- }
+ cancellationToken.ThrowIfCancellationRequested();
- FileSystemHelper.DeleteEmptyFolders(_fileSystem, directory, _logger);
+ FileSystemHelper.DeleteFile(_fileSystem, file.FullName, _logger);
- progress.Report(100);
+ index++;
}
+
+ FileSystemHelper.DeleteEmptyFolders(_fileSystem, directory, _logger);
+
+ progress.Report(100);
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
index a091c2bd9..699529527 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
@@ -9,93 +9,93 @@ using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Tasks;
-namespace Emby.Server.Implementations.ScheduledTasks.Tasks
+namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
+
+/// <summary>
+/// Deletes old log files.
+/// </summary>
+public class DeleteLogFileTask : IScheduledTask, IConfigurableScheduledTask
{
+ private readonly IConfigurationManager _configurationManager;
+ private readonly IFileSystem _fileSystem;
+ private readonly ILocalizationManager _localization;
+
/// <summary>
- /// Deletes old log files.
+ /// Initializes a new instance of the <see cref="DeleteLogFileTask" /> class.
/// </summary>
- public class DeleteLogFileTask : IScheduledTask, IConfigurableScheduledTask
+ /// <param name="configurationManager">Instance of the <see cref="IConfigurationManager"/> interface.</param>
+ /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
+ /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
+ public DeleteLogFileTask(IConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization)
{
- private readonly IConfigurationManager _configurationManager;
- private readonly IFileSystem _fileSystem;
- private readonly ILocalizationManager _localization;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="DeleteLogFileTask" /> class.
- /// </summary>
- /// <param name="configurationManager">Instance of the <see cref="IConfigurationManager"/> interface.</param>
- /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
- /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
- public DeleteLogFileTask(IConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization)
- {
- _configurationManager = configurationManager;
- _fileSystem = fileSystem;
- _localization = localization;
- }
+ _configurationManager = configurationManager;
+ _fileSystem = fileSystem;
+ _localization = localization;
+ }
- /// <inheritdoc />
- public string Name => _localization.GetLocalizedString("TaskCleanLogs");
+ /// <inheritdoc />
+ public string Name => _localization.GetLocalizedString("TaskCleanLogs");
- /// <inheritdoc />
- public string Description => string.Format(
- CultureInfo.InvariantCulture,
- _localization.GetLocalizedString("TaskCleanLogsDescription"),
- _configurationManager.CommonConfiguration.LogFileRetentionDays);
+ /// <inheritdoc />
+ public string Description => string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("TaskCleanLogsDescription"),
+ _configurationManager.CommonConfiguration.LogFileRetentionDays);
- /// <inheritdoc />
- public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
+ /// <inheritdoc />
+ public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
- /// <inheritdoc />
- public string Key => "CleanLogFiles";
+ /// <inheritdoc />
+ public string Key => "CleanLogFiles";
- /// <inheritdoc />
- public bool IsHidden => false;
+ /// <inheritdoc />
+ public bool IsHidden => false;
- /// <inheritdoc />
- public bool IsEnabled => true;
+ /// <inheritdoc />
+ public bool IsEnabled => true;
- /// <inheritdoc />
- public bool IsLogged => true;
+ /// <inheritdoc />
+ public bool IsLogged => true;
- /// <inheritdoc />
- public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ /// <inheritdoc />
+ public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ {
+ yield return new TaskTriggerInfo
{
- return
- [
- new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks }
- ];
- }
+ Type = TaskTriggerInfoType.IntervalTrigger,
+ IntervalTicks = TimeSpan.FromHours(24).Ticks
+ };
+ }
- /// <inheritdoc />
- public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
- {
- // Delete log files more than n days old
- var minDateModified = DateTime.UtcNow.AddDays(-_configurationManager.CommonConfiguration.LogFileRetentionDays);
+ /// <inheritdoc />
+ public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ // Delete log files more than n days old
+ var minDateModified = DateTime.UtcNow.AddDays(-_configurationManager.CommonConfiguration.LogFileRetentionDays);
- // Only delete files that serilog doesn't manage (anything that doesn't start with 'log_'
- var filesToDelete = _fileSystem.GetFiles(_configurationManager.CommonApplicationPaths.LogDirectoryPath, true)
- .Where(f => !f.Name.StartsWith("log_", StringComparison.Ordinal)
- && _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
- .ToList();
+ // Only delete files that serilog doesn't manage (anything that doesn't start with 'log_'
+ var filesToDelete = _fileSystem.GetFiles(_configurationManager.CommonApplicationPaths.LogDirectoryPath, true)
+ .Where(f => !f.Name.StartsWith("log_", StringComparison.Ordinal)
+ && _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
+ .ToList();
- var index = 0;
+ var index = 0;
- foreach (var file in filesToDelete)
- {
- double percent = index / (double)filesToDelete.Count;
+ foreach (var file in filesToDelete)
+ {
+ double percent = index / (double)filesToDelete.Count;
- progress.Report(100 * percent);
+ progress.Report(100 * percent);
- cancellationToken.ThrowIfCancellationRequested();
+ cancellationToken.ThrowIfCancellationRequested();
- _fileSystem.DeleteFile(file.FullName);
+ _fileSystem.DeleteFile(file.FullName);
- index++;
- }
+ index++;
+ }
- progress.Report(100);
+ progress.Report(100);
- return Task.CompletedTask;
- }
+ return Task.CompletedTask;
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs
index d0896cc81..9cc2cc512 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs
@@ -10,118 +10,115 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
-namespace Emby.Server.Implementations.ScheduledTasks.Tasks
+namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
+
+/// <summary>
+/// Deletes all transcoding temp files.
+/// </summary>
+public class DeleteTranscodeFileTask : IScheduledTask, IConfigurableScheduledTask
{
+ private readonly ILogger<DeleteTranscodeFileTask> _logger;
+ private readonly IConfigurationManager _configurationManager;
+ private readonly IFileSystem _fileSystem;
+ private readonly ILocalizationManager _localization;
+
/// <summary>
- /// Deletes all transcoding temp files.
+ /// Initializes a new instance of the <see cref="DeleteTranscodeFileTask"/> class.
/// </summary>
- public class DeleteTranscodeFileTask : IScheduledTask, IConfigurableScheduledTask
+ /// <param name="logger">Instance of the <see cref="ILogger{DeleteTranscodeFileTask}"/> interface.</param>
+ /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
+ /// <param name="configurationManager">Instance of the <see cref="IConfigurationManager"/> interface.</param>
+ /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
+ public DeleteTranscodeFileTask(
+ ILogger<DeleteTranscodeFileTask> logger,
+ IFileSystem fileSystem,
+ IConfigurationManager configurationManager,
+ ILocalizationManager localization)
{
- private readonly ILogger<DeleteTranscodeFileTask> _logger;
- private readonly IConfigurationManager _configurationManager;
- private readonly IFileSystem _fileSystem;
- private readonly ILocalizationManager _localization;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="DeleteTranscodeFileTask"/> class.
- /// </summary>
- /// <param name="logger">Instance of the <see cref="ILogger{DeleteTranscodeFileTask}"/> interface.</param>
- /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
- /// <param name="configurationManager">Instance of the <see cref="IConfigurationManager"/> interface.</param>
- /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
- public DeleteTranscodeFileTask(
- ILogger<DeleteTranscodeFileTask> logger,
- IFileSystem fileSystem,
- IConfigurationManager configurationManager,
- ILocalizationManager localization)
- {
- _logger = logger;
- _fileSystem = fileSystem;
- _configurationManager = configurationManager;
- _localization = localization;
- }
+ _logger = logger;
+ _fileSystem = fileSystem;
+ _configurationManager = configurationManager;
+ _localization = localization;
+ }
- /// <inheritdoc />
- public string Name => _localization.GetLocalizedString("TaskCleanTranscode");
+ /// <inheritdoc />
+ public string Name => _localization.GetLocalizedString("TaskCleanTranscode");
- /// <inheritdoc />
- public string Description => _localization.GetLocalizedString("TaskCleanTranscodeDescription");
+ /// <inheritdoc />
+ public string Description => _localization.GetLocalizedString("TaskCleanTranscodeDescription");
- /// <inheritdoc />
- public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
+ /// <inheritdoc />
+ public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
- /// <inheritdoc />
- public string Key => "DeleteTranscodeFiles";
+ /// <inheritdoc />
+ public string Key => "DeleteTranscodeFiles";
- /// <inheritdoc />
- public bool IsHidden => false;
+ /// <inheritdoc />
+ public bool IsHidden => false;
- /// <inheritdoc />
- public bool IsEnabled => true;
+ /// <inheritdoc />
+ public bool IsEnabled => true;
- /// <inheritdoc />
- public bool IsLogged => true;
+ /// <inheritdoc />
+ public bool IsLogged => true;
- /// <inheritdoc />
- public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ /// <inheritdoc />
+ public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ {
+ yield return new TaskTriggerInfo
{
- return
- [
- new TaskTriggerInfo
- {
- Type = TaskTriggerInfoType.StartupTrigger
- },
- new TaskTriggerInfo
- {
- Type = TaskTriggerInfoType.IntervalTrigger,
- IntervalTicks = TimeSpan.FromHours(24).Ticks
- }
- ];
- }
+ Type = TaskTriggerInfoType.StartupTrigger
+ };
- /// <inheritdoc />
- public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ yield return new TaskTriggerInfo
{
- var minDateModified = DateTime.UtcNow.AddDays(-1);
- progress.Report(50);
-
- DeleteTempFilesFromDirectory(_configurationManager.GetTranscodePath(), minDateModified, progress, cancellationToken);
+ Type = TaskTriggerInfoType.IntervalTrigger,
+ IntervalTicks = TimeSpan.FromHours(24).Ticks
+ };
+ }
- return Task.CompletedTask;
- }
+ /// <inheritdoc />
+ public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ var minDateModified = DateTime.UtcNow.AddDays(-1);
+ progress.Report(50);
- /// <summary>
- /// Deletes the transcoded temp files from directory with a last write time less than a given date.
- /// </summary>
- /// <param name="directory">The directory.</param>
- /// <param name="minDateModified">The min date modified.</param>
- /// <param name="progress">The progress.</param>
- /// <param name="cancellationToken">The task cancellation token.</param>
- private void DeleteTempFilesFromDirectory(string directory, DateTime minDateModified, IProgress<double> progress, CancellationToken cancellationToken)
- {
- var filesToDelete = _fileSystem.GetFiles(directory, true)
- .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
- .ToList();
+ DeleteTempFilesFromDirectory(_configurationManager.GetTranscodePath(), minDateModified, progress, cancellationToken);
- var index = 0;
+ return Task.CompletedTask;
+ }
- foreach (var file in filesToDelete)
- {
- double percent = index;
- percent /= filesToDelete.Count;
+ /// <summary>
+ /// Deletes the transcoded temp files from directory with a last write time less than a given date.
+ /// </summary>
+ /// <param name="directory">The directory.</param>
+ /// <param name="minDateModified">The min date modified.</param>
+ /// <param name="progress">The progress.</param>
+ /// <param name="cancellationToken">The task cancellation token.</param>
+ private void DeleteTempFilesFromDirectory(string directory, DateTime minDateModified, IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ var filesToDelete = _fileSystem.GetFiles(directory, true)
+ .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
+ .ToList();
- progress.Report(100 * percent);
+ var index = 0;
- cancellationToken.ThrowIfCancellationRequested();
+ foreach (var file in filesToDelete)
+ {
+ double percent = index;
+ percent /= filesToDelete.Count;
- FileSystemHelper.DeleteFile(_fileSystem, file.FullName, _logger);
+ progress.Report(100 * percent);
- index++;
- }
+ cancellationToken.ThrowIfCancellationRequested();
- FileSystemHelper.DeleteEmptyFolders(_fileSystem, directory, _logger);
+ FileSystemHelper.DeleteFile(_fileSystem, file.FullName, _logger);
- progress.Report(100);
+ index++;
}
+
+ FileSystemHelper.DeleteEmptyFolders(_fileSystem, directory, _logger);
+
+ progress.Report(100);
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs
index de1e60d30..51920c5b1 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs
@@ -4,10 +4,10 @@ using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Enums;
-using MediaBrowser.Controller;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.MediaSegments;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Tasks;
@@ -62,11 +62,11 @@ public class MediaSegmentExtractionTask : IScheduledTask
var query = new InternalItemsQuery
{
- MediaTypes = new[] { MediaType.Video, MediaType.Audio },
+ MediaTypes = [MediaType.Video, MediaType.Audio],
IsVirtualItem = false,
IncludeItemTypes = _itemTypes,
DtoOptions = new DtoOptions(true),
- SourceTypes = new[] { SourceType.Library },
+ SourceTypes = [SourceType.Library],
Recursive = true,
Limit = pagesize
};
@@ -91,7 +91,8 @@ public class MediaSegmentExtractionTask : IScheduledTask
// Only local files supported
if (item.IsFileProtocol && File.Exists(item.Path))
{
- await _mediaSegmentManager.RunSegmentPluginProviders(item, false, cancellationToken).ConfigureAwait(false);
+ var libraryOptions = _libraryManager.GetLibraryOptions(item);
+ await _mediaSegmentManager.RunSegmentPluginProviders(item, libraryOptions, false, cancellationToken).ConfigureAwait(false);
}
// Update progress
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs
index 7d4e2377d..bf8ffaf47 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs
@@ -2,96 +2,81 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Server.Implementations;
+using Jellyfin.Database.Implementations;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Tasks;
-using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
-namespace Emby.Server.Implementations.ScheduledTasks.Tasks
+namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
+
+/// <summary>
+/// Optimizes Jellyfin's database by issuing a VACUUM command.
+/// </summary>
+public class OptimizeDatabaseTask : IScheduledTask, IConfigurableScheduledTask
{
+ private readonly ILogger<OptimizeDatabaseTask> _logger;
+ private readonly ILocalizationManager _localization;
+ private readonly IJellyfinDatabaseProvider _jellyfinDatabaseProvider;
+
/// <summary>
- /// Optimizes Jellyfin's database by issuing a VACUUM command.
+ /// Initializes a new instance of the <see cref="OptimizeDatabaseTask" /> class.
/// </summary>
- public class OptimizeDatabaseTask : IScheduledTask, IConfigurableScheduledTask
+ /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
+ /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
+ /// <param name="jellyfinDatabaseProvider">Instance of the JellyfinDatabaseProvider that can be used for provider specific operations.</param>
+ public OptimizeDatabaseTask(
+ ILogger<OptimizeDatabaseTask> logger,
+ ILocalizationManager localization,
+ IJellyfinDatabaseProvider jellyfinDatabaseProvider)
{
- private readonly ILogger<OptimizeDatabaseTask> _logger;
- private readonly ILocalizationManager _localization;
- private readonly IDbContextFactory<JellyfinDbContext> _provider;
+ _logger = logger;
+ _localization = localization;
+ _jellyfinDatabaseProvider = jellyfinDatabaseProvider;
+ }
- /// <summary>
- /// Initializes a new instance of the <see cref="OptimizeDatabaseTask" /> class.
- /// </summary>
- /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
- /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
- /// <param name="provider">Instance of the <see cref="IDbContextFactory{JellyfinDbContext}"/> interface.</param>
- public OptimizeDatabaseTask(
- ILogger<OptimizeDatabaseTask> logger,
- ILocalizationManager localization,
- IDbContextFactory<JellyfinDbContext> provider)
- {
- _logger = logger;
- _localization = localization;
- _provider = provider;
- }
+ /// <inheritdoc />
+ public string Name => _localization.GetLocalizedString("TaskOptimizeDatabase");
+
+ /// <inheritdoc />
+ public string Description => _localization.GetLocalizedString("TaskOptimizeDatabaseDescription");
- /// <inheritdoc />
- public string Name => _localization.GetLocalizedString("TaskOptimizeDatabase");
+ /// <inheritdoc />
+ public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
- /// <inheritdoc />
- public string Description => _localization.GetLocalizedString("TaskOptimizeDatabaseDescription");
+ /// <inheritdoc />
+ public string Key => "OptimizeDatabaseTask";
- /// <inheritdoc />
- public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
+ /// <inheritdoc />
+ public bool IsHidden => false;
- /// <inheritdoc />
- public string Key => "OptimizeDatabaseTask";
+ /// <inheritdoc />
+ public bool IsEnabled => true;
- /// <inheritdoc />
- public bool IsHidden => false;
+ /// <inheritdoc />
+ public bool IsLogged => true;
- /// <inheritdoc />
- public bool IsEnabled => true;
+ /// <inheritdoc />
+ public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ {
+ yield return new TaskTriggerInfo
+ {
+ Type = TaskTriggerInfoType.IntervalTrigger,
+ IntervalTicks = TimeSpan.FromHours(24).Ticks
+ };
+ }
- /// <inheritdoc />
- public bool IsLogged => true;
+ /// <inheritdoc />
+ public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ _logger.LogInformation("Optimizing and vacuuming jellyfin.db...");
- /// <inheritdoc />
- public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ try
{
- return
- [
- // Every so often
- new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks }
- ];
+ await _jellyfinDatabaseProvider.RunScheduledOptimisation(cancellationToken).ConfigureAwait(false);
}
-
- /// <inheritdoc />
- public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ catch (Exception e)
{
- _logger.LogInformation("Optimizing and vacuuming jellyfin.db...");
-
- try
- {
- var context = await _provider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
- await using (context.ConfigureAwait(false))
- {
- if (context.Database.IsSqlite())
- {
- await context.Database.ExecuteSqlRawAsync("PRAGMA optimize", cancellationToken).ConfigureAwait(false);
- await context.Database.ExecuteSqlRawAsync("VACUUM", cancellationToken).ConfigureAwait(false);
- _logger.LogInformation("jellyfin.db optimized successfully!");
- }
- else
- {
- _logger.LogInformation("This database doesn't support optimization");
- }
- }
- }
- catch (Exception e)
- {
- _logger.LogError(e, "Error while optimizing jellyfin.db");
- }
+ _logger.LogError(e, "Error while optimizing jellyfin.db");
}
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs
index 2907f18b5..18162ad2f 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs
@@ -6,68 +6,64 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Tasks;
-namespace Emby.Server.Implementations.ScheduledTasks.Tasks
+namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
+
+/// <summary>
+/// Class PeopleValidationTask.
+/// </summary>
+public class PeopleValidationTask : IScheduledTask, IConfigurableScheduledTask
{
+ private readonly ILibraryManager _libraryManager;
+ private readonly ILocalizationManager _localization;
+
/// <summary>
- /// Class PeopleValidationTask.
+ /// Initializes a new instance of the <see cref="PeopleValidationTask" /> class.
/// </summary>
- public class PeopleValidationTask : IScheduledTask, IConfigurableScheduledTask
+ /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
+ /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
+ public PeopleValidationTask(ILibraryManager libraryManager, ILocalizationManager localization)
{
- private readonly ILibraryManager _libraryManager;
- private readonly ILocalizationManager _localization;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="PeopleValidationTask" /> class.
- /// </summary>
- /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
- /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
- public PeopleValidationTask(ILibraryManager libraryManager, ILocalizationManager localization)
- {
- _libraryManager = libraryManager;
- _localization = localization;
- }
+ _libraryManager = libraryManager;
+ _localization = localization;
+ }
- /// <inheritdoc />
- public string Name => _localization.GetLocalizedString("TaskRefreshPeople");
+ /// <inheritdoc />
+ public string Name => _localization.GetLocalizedString("TaskRefreshPeople");
- /// <inheritdoc />
- public string Description => _localization.GetLocalizedString("TaskRefreshPeopleDescription");
+ /// <inheritdoc />
+ public string Description => _localization.GetLocalizedString("TaskRefreshPeopleDescription");
- /// <inheritdoc />
- public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
+ /// <inheritdoc />
+ public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
- /// <inheritdoc />
- public string Key => "RefreshPeople";
+ /// <inheritdoc />
+ public string Key => "RefreshPeople";
- /// <inheritdoc />
- public bool IsHidden => false;
+ /// <inheritdoc />
+ public bool IsHidden => false;
- /// <inheritdoc />
- public bool IsEnabled => true;
+ /// <inheritdoc />
+ public bool IsEnabled => true;
- /// <inheritdoc />
- public bool IsLogged => true;
+ /// <inheritdoc />
+ public bool IsLogged => true;
- /// <summary>
- /// Creates the triggers that define when the task will run.
- /// </summary>
- /// <returns>An <see cref="IEnumerable{TaskTriggerInfo}"/> containing the default trigger infos for this task.</returns>
- public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ /// <summary>
+ /// Creates the triggers that define when the task will run.
+ /// </summary>
+ /// <returns>An <see cref="IEnumerable{TaskTriggerInfo}"/> containing the default trigger infos for this task.</returns>
+ public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ {
+ yield return new TaskTriggerInfo
{
- return new[]
- {
- new TaskTriggerInfo
- {
- Type = TaskTriggerInfoType.IntervalTrigger,
- IntervalTicks = TimeSpan.FromDays(7).Ticks
- }
- };
- }
+ Type = TaskTriggerInfoType.IntervalTrigger,
+ IntervalTicks = TimeSpan.FromDays(7).Ticks
+ };
+ }
- /// <inheritdoc />
- public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
- {
- return _libraryManager.ValidatePeopleAsync(progress, cancellationToken);
- }
+ /// <inheritdoc />
+ public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ return _libraryManager.ValidatePeopleAsync(progress, cancellationToken);
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs
index b74f4d1b2..31153af20 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs
@@ -10,111 +10,115 @@ using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
-namespace Emby.Server.Implementations.ScheduledTasks.Tasks
+namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
+
+/// <summary>
+/// Plugin Update Task.
+/// </summary>
+public class PluginUpdateTask : IScheduledTask, IConfigurableScheduledTask
{
+ private readonly ILogger<PluginUpdateTask> _logger;
+
+ private readonly IInstallationManager _installationManager;
+ private readonly ILocalizationManager _localization;
+
/// <summary>
- /// Plugin Update Task.
+ /// Initializes a new instance of the <see cref="PluginUpdateTask" /> class.
/// </summary>
- public class PluginUpdateTask : IScheduledTask, IConfigurableScheduledTask
+ /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
+ /// <param name="installationManager">Instance of the <see cref="IInstallationManager"/> interface.</param>
+ /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
+ public PluginUpdateTask(ILogger<PluginUpdateTask> logger, IInstallationManager installationManager, ILocalizationManager localization)
{
- private readonly ILogger<PluginUpdateTask> _logger;
-
- private readonly IInstallationManager _installationManager;
- private readonly ILocalizationManager _localization;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="PluginUpdateTask" /> class.
- /// </summary>
- /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
- /// <param name="installationManager">Instance of the <see cref="IInstallationManager"/> interface.</param>
- /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
- public PluginUpdateTask(ILogger<PluginUpdateTask> logger, IInstallationManager installationManager, ILocalizationManager localization)
- {
- _logger = logger;
- _installationManager = installationManager;
- _localization = localization;
- }
+ _logger = logger;
+ _installationManager = installationManager;
+ _localization = localization;
+ }
- /// <inheritdoc />
- public string Name => _localization.GetLocalizedString("TaskUpdatePlugins");
+ /// <inheritdoc />
+ public string Name => _localization.GetLocalizedString("TaskUpdatePlugins");
- /// <inheritdoc />
- public string Description => _localization.GetLocalizedString("TaskUpdatePluginsDescription");
+ /// <inheritdoc />
+ public string Description => _localization.GetLocalizedString("TaskUpdatePluginsDescription");
- /// <inheritdoc />
- public string Category => _localization.GetLocalizedString("TasksApplicationCategory");
+ /// <inheritdoc />
+ public string Category => _localization.GetLocalizedString("TasksApplicationCategory");
- /// <inheritdoc />
- public string Key => "PluginUpdates";
+ /// <inheritdoc />
+ public string Key => "PluginUpdates";
- /// <inheritdoc />
- public bool IsHidden => false;
+ /// <inheritdoc />
+ public bool IsHidden => false;
- /// <inheritdoc />
- public bool IsEnabled => true;
+ /// <inheritdoc />
+ public bool IsEnabled => true;
- /// <inheritdoc />
- public bool IsLogged => true;
+ /// <inheritdoc />
+ public bool IsLogged => true;
- /// <inheritdoc />
- public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ /// <inheritdoc />
+ public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ {
+ yield return new TaskTriggerInfo
{
- // At startup
- yield return new TaskTriggerInfo { Type = TaskTriggerInfoType.StartupTrigger };
-
- // Every so often
- yield return new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks };
- }
+ Type = TaskTriggerInfoType.StartupTrigger
+ };
- /// <inheritdoc />
- public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ yield return new TaskTriggerInfo
{
- progress.Report(0);
+ Type = TaskTriggerInfoType.IntervalTrigger,
+ IntervalTicks = TimeSpan.FromHours(24).Ticks
+ };
+ }
- var packageFetchTask = _installationManager.GetAvailablePluginUpdates(cancellationToken);
- var packagesToInstall = (await packageFetchTask.ConfigureAwait(false)).ToList();
+ /// <inheritdoc />
+ public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ progress.Report(0);
- progress.Report(10);
+ var packageFetchTask = _installationManager.GetAvailablePluginUpdates(cancellationToken);
+ var packagesToInstall = (await packageFetchTask.ConfigureAwait(false)).ToList();
- var numComplete = 0;
+ progress.Report(10);
- foreach (var package in packagesToInstall)
- {
- cancellationToken.ThrowIfCancellationRequested();
+ var numComplete = 0;
- try
- {
- await _installationManager.InstallPackage(package, cancellationToken).ConfigureAwait(false);
- }
- catch (OperationCanceledException)
- {
- // InstallPackage has its own inner cancellation token, so only throw this if it's ours
- if (cancellationToken.IsCancellationRequested)
- {
- throw;
- }
- }
- catch (HttpRequestException ex)
- {
- _logger.LogError(ex, "Error downloading {0}", package.Name);
- }
- catch (IOException ex)
- {
- _logger.LogError(ex, "Error updating {0}", package.Name);
- }
- catch (InvalidDataException ex)
- {
- _logger.LogError(ex, "Error updating {0}", package.Name);
- }
+ foreach (var package in packagesToInstall)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
- // Update progress
- lock (progress)
+ try
+ {
+ await _installationManager.InstallPackage(package, cancellationToken).ConfigureAwait(false);
+ }
+ catch (OperationCanceledException)
+ {
+ // InstallPackage has its own inner cancellation token, so only throw this if it's ours
+ if (cancellationToken.IsCancellationRequested)
{
- progress.Report((90.0 * ++numComplete / packagesToInstall.Count) + 10);
+ throw;
}
}
+ catch (HttpRequestException ex)
+ {
+ _logger.LogError(ex, "Error downloading {Name}", package.Name);
+ }
+ catch (IOException ex)
+ {
+ _logger.LogError(ex, "Error updating {Name}", package.Name);
+ }
+ catch (InvalidDataException ex)
+ {
+ _logger.LogError(ex, "Error updating {Name}", package.Name);
+ }
- progress.Report(100);
+ // Update progress
+ lock (progress)
+ {
+ progress.Report((90.0 * ++numComplete / packagesToInstall.Count) + 10);
+ }
}
+
+ progress.Report(100);
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
index 172448dde..1865189d0 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
@@ -7,60 +7,59 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Tasks;
-namespace Emby.Server.Implementations.ScheduledTasks.Tasks
+namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
+
+/// <summary>
+/// Class RefreshMediaLibraryTask.
+/// </summary>
+public class RefreshMediaLibraryTask : IScheduledTask
{
/// <summary>
- /// Class RefreshMediaLibraryTask.
+ /// The _library manager.
/// </summary>
- public class RefreshMediaLibraryTask : IScheduledTask
- {
- /// <summary>
- /// The _library manager.
- /// </summary>
- private readonly ILibraryManager _libraryManager;
- private readonly ILocalizationManager _localization;
+ private readonly ILibraryManager _libraryManager;
+ private readonly ILocalizationManager _localization;
- /// <summary>
- /// Initializes a new instance of the <see cref="RefreshMediaLibraryTask" /> class.
- /// </summary>
- /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
- /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
- public RefreshMediaLibraryTask(ILibraryManager libraryManager, ILocalizationManager localization)
- {
- _libraryManager = libraryManager;
- _localization = localization;
- }
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RefreshMediaLibraryTask" /> class.
+ /// </summary>
+ /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
+ /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
+ public RefreshMediaLibraryTask(ILibraryManager libraryManager, ILocalizationManager localization)
+ {
+ _libraryManager = libraryManager;
+ _localization = localization;
+ }
- /// <inheritdoc />
- public string Name => _localization.GetLocalizedString("TaskRefreshLibrary");
+ /// <inheritdoc />
+ public string Name => _localization.GetLocalizedString("TaskRefreshLibrary");
- /// <inheritdoc />
- public string Description => _localization.GetLocalizedString("TaskRefreshLibraryDescription");
+ /// <inheritdoc />
+ public string Description => _localization.GetLocalizedString("TaskRefreshLibraryDescription");
- /// <inheritdoc />
- public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
+ /// <inheritdoc />
+ public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
- /// <inheritdoc />
- public string Key => "RefreshLibrary";
+ /// <inheritdoc />
+ public string Key => "RefreshLibrary";
- /// <inheritdoc />
- public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ /// <inheritdoc />
+ public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+ {
+ yield return new TaskTriggerInfo
{
- yield return new TaskTriggerInfo
- {
- Type = TaskTriggerInfoType.IntervalTrigger,
- IntervalTicks = TimeSpan.FromHours(12).Ticks
- };
- }
+ Type = TaskTriggerInfoType.IntervalTrigger,
+ IntervalTicks = TimeSpan.FromHours(12).Ticks
+ };
+ }
- /// <inheritdoc />
- public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
+ /// <inheritdoc />
+ public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
- progress.Report(0);
+ progress.Report(0);
- return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken);
- }
+ await ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken).ConfigureAwait(false);
}
}