aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/ScheduledTasks
diff options
context:
space:
mode:
authorShadowghost <Ghost_of_Stone@web.de>2025-04-30 09:29:13 +0200
committerShadowghost <Ghost_of_Stone@web.de>2025-04-30 09:29:13 +0200
commit5c9f70c3752bd7297cb85bdc7ce748363a16ad8b (patch)
treef70195e156acc7ef112dd9a13382b95661c579c8 /Emby.Server.Implementations/ScheduledTasks
parentaa24d08d3363cf164ec7d15ac16ac8c04e4e3342 (diff)
Cleanup Tasks and Validators
Diffstat (limited to 'Emby.Server.Implementations/ScheduledTasks')
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs987
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/TaskManager.cs379
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs15
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs228
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs101
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/CleanupCollectionAndPlaylistPathsTask.cs11
-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.cs4
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs114
-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
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs121
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs155
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs69
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs161
18 files changed, 1582 insertions, 1608 deletions
diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
index 985f0a8f8..24f554981 100644
--- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
@@ -16,663 +16,662 @@ using MediaBrowser.Common.Extensions;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
-namespace Emby.Server.Implementations.ScheduledTasks
+namespace Emby.Server.Implementations.ScheduledTasks;
+
+/// <summary>
+/// Class ScheduledTaskWorker.
+/// </summary>
+public class ScheduledTaskWorker : IScheduledTaskWorker
{
+ private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
+ private readonly IApplicationPaths _applicationPaths;
+ private readonly ILogger _logger;
+ private readonly ITaskManager _taskManager;
+ private readonly Lock _lastExecutionResultSyncLock = new();
+ private bool _readFromFile;
+ private TaskResult _lastExecutionResult;
+ private Task _currentTask;
+ private Tuple<TaskTriggerInfo, ITaskTrigger>[] _triggers;
+ private string _id;
+
/// <summary>
- /// Class ScheduledTaskWorker.
+ /// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class.
/// </summary>
- public class ScheduledTaskWorker : IScheduledTaskWorker
+ /// <param name="scheduledTask">The scheduled task.</param>
+ /// <param name="applicationPaths">The application paths.</param>
+ /// <param name="taskManager">The task manager.</param>
+ /// <param name="logger">The logger.</param>
+ /// <exception cref="ArgumentNullException">
+ /// scheduledTask
+ /// or
+ /// applicationPaths
+ /// or
+ /// taskManager
+ /// or
+ /// jsonSerializer
+ /// or
+ /// logger.
+ /// </exception>
+ public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, ILogger logger)
{
- private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
- private readonly IApplicationPaths _applicationPaths;
- private readonly ILogger _logger;
- private readonly ITaskManager _taskManager;
- private readonly Lock _lastExecutionResultSyncLock = new();
- private bool _readFromFile;
- private TaskResult _lastExecutionResult;
- private Task _currentTask;
- private Tuple<TaskTriggerInfo, ITaskTrigger>[] _triggers;
- private string _id;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class.
- /// </summary>
- /// <param name="scheduledTask">The scheduled task.</param>
- /// <param name="applicationPaths">The application paths.</param>
- /// <param name="taskManager">The task manager.</param>
- /// <param name="logger">The logger.</param>
- /// <exception cref="ArgumentNullException">
- /// scheduledTask
- /// or
- /// applicationPaths
- /// or
- /// taskManager
- /// or
- /// jsonSerializer
- /// or
- /// logger.
- /// </exception>
- public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, ILogger logger)
- {
- ArgumentNullException.ThrowIfNull(scheduledTask);
- ArgumentNullException.ThrowIfNull(applicationPaths);
- ArgumentNullException.ThrowIfNull(taskManager);
- ArgumentNullException.ThrowIfNull(logger);
+ ArgumentNullException.ThrowIfNull(scheduledTask);
+ ArgumentNullException.ThrowIfNull(applicationPaths);
+ ArgumentNullException.ThrowIfNull(taskManager);
+ ArgumentNullException.ThrowIfNull(logger);
- ScheduledTask = scheduledTask;
- _applicationPaths = applicationPaths;
- _taskManager = taskManager;
- _logger = logger;
+ ScheduledTask = scheduledTask;
+ _applicationPaths = applicationPaths;
+ _taskManager = taskManager;
+ _logger = logger;
- InitTriggerEvents();
- }
+ InitTriggerEvents();
+ }
- /// <inheritdoc />
- public event EventHandler<GenericEventArgs<double>> TaskProgress;
+ /// <inheritdoc />
+ public event EventHandler<GenericEventArgs<double>> TaskProgress;
- /// <inheritdoc />
- public IScheduledTask ScheduledTask { get; private set; }
+ /// <inheritdoc />
+ public IScheduledTask ScheduledTask { get; private set; }
- /// <inheritdoc />
- public TaskResult LastExecutionResult
+ /// <inheritdoc />
+ public TaskResult LastExecutionResult
+ {
+ get
{
- get
- {
- var path = GetHistoryFilePath();
+ var path = GetHistoryFilePath();
- lock (_lastExecutionResultSyncLock)
+ lock (_lastExecutionResultSyncLock)
+ {
+ if (_lastExecutionResult is null && !_readFromFile)
{
- if (_lastExecutionResult is null && !_readFromFile)
+ if (File.Exists(path))
{
- if (File.Exists(path))
+ var bytes = File.ReadAllBytes(path);
+ if (bytes.Length > 0)
{
- var bytes = File.ReadAllBytes(path);
- if (bytes.Length > 0)
+ try
{
- try
- {
- _lastExecutionResult = JsonSerializer.Deserialize<TaskResult>(bytes, _jsonOptions);
- }
- catch (JsonException ex)
- {
- _logger.LogError(ex, "Error deserializing {File}", path);
- }
+ _lastExecutionResult = JsonSerializer.Deserialize<TaskResult>(bytes, _jsonOptions);
}
- else
+ catch (JsonException ex)
{
- _logger.LogDebug("Scheduled Task history file {Path} is empty. Skipping deserialization.", path);
+ _logger.LogError(ex, "Error deserializing {File}", path);
}
}
-
- _readFromFile = true;
+ else
+ {
+ _logger.LogDebug("Scheduled Task history file {Path} is empty. Skipping deserialization.", path);
+ }
}
- }
- return _lastExecutionResult;
+ _readFromFile = true;
+ }
}
- private set
- {
- _lastExecutionResult = value;
+ return _lastExecutionResult;
+ }
- var path = GetHistoryFilePath();
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ private set
+ {
+ _lastExecutionResult = value;
- lock (_lastExecutionResultSyncLock)
- {
- using FileStream createStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
- using Utf8JsonWriter jsonStream = new Utf8JsonWriter(createStream);
- JsonSerializer.Serialize(jsonStream, value, _jsonOptions);
- }
+ var path = GetHistoryFilePath();
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+
+ lock (_lastExecutionResultSyncLock)
+ {
+ using FileStream createStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
+ using Utf8JsonWriter jsonStream = new Utf8JsonWriter(createStream);
+ JsonSerializer.Serialize(jsonStream, value, _jsonOptions);
}
}
+ }
- /// <inheritdoc />
- public string Name => ScheduledTask.Name;
+ /// <inheritdoc />
+ public string Name => ScheduledTask.Name;
- /// <inheritdoc />
- public string Description => ScheduledTask.Description;
+ /// <inheritdoc />
+ public string Description => ScheduledTask.Description;
- /// <inheritdoc />
- public string Category => ScheduledTask.Category;
+ /// <inheritdoc />
+ public string Category => ScheduledTask.Category;
- /// <summary>
- /// Gets or sets the current cancellation token.
- /// </summary>
- /// <value>The current cancellation token source.</value>
- private CancellationTokenSource CurrentCancellationTokenSource { get; set; }
+ /// <summary>
+ /// Gets or sets the current cancellation token.
+ /// </summary>
+ /// <value>The current cancellation token source.</value>
+ private CancellationTokenSource CurrentCancellationTokenSource { get; set; }
- /// <summary>
- /// Gets or sets the current execution start time.
- /// </summary>
- /// <value>The current execution start time.</value>
- private DateTime CurrentExecutionStartTime { get; set; }
+ /// <summary>
+ /// Gets or sets the current execution start time.
+ /// </summary>
+ /// <value>The current execution start time.</value>
+ private DateTime CurrentExecutionStartTime { get; set; }
- /// <inheritdoc />
- public TaskState State
+ /// <inheritdoc />
+ public TaskState State
+ {
+ get
{
- get
+ if (CurrentCancellationTokenSource is not null)
{
- if (CurrentCancellationTokenSource is not null)
- {
- return CurrentCancellationTokenSource.IsCancellationRequested
- ? TaskState.Cancelling
- : TaskState.Running;
- }
-
- return TaskState.Idle;
+ return CurrentCancellationTokenSource.IsCancellationRequested
+ ? TaskState.Cancelling
+ : TaskState.Running;
}
+
+ return TaskState.Idle;
}
+ }
- /// <inheritdoc />
- public double? CurrentProgress { get; private set; }
+ /// <inheritdoc />
+ public double? CurrentProgress { get; private set; }
- /// <summary>
- /// Gets or sets the triggers that define when the task will run.
- /// </summary>
- /// <value>The triggers.</value>
- private Tuple<TaskTriggerInfo, ITaskTrigger>[] InternalTriggers
+ /// <summary>
+ /// Gets or sets the triggers that define when the task will run.
+ /// </summary>
+ /// <value>The triggers.</value>
+ private Tuple<TaskTriggerInfo, ITaskTrigger>[] InternalTriggers
+ {
+ get => _triggers;
+ set
{
- get => _triggers;
- set
- {
- ArgumentNullException.ThrowIfNull(value);
+ ArgumentNullException.ThrowIfNull(value);
- // Cleanup current triggers
- if (_triggers is not null)
- {
- DisposeTriggers();
- }
+ // Cleanup current triggers
+ if (_triggers is not null)
+ {
+ DisposeTriggers();
+ }
- _triggers = value.ToArray();
+ _triggers = value.ToArray();
- ReloadTriggerEvents(false);
- }
+ ReloadTriggerEvents(false);
}
+ }
- /// <inheritdoc />
- public IReadOnlyList<TaskTriggerInfo> Triggers
+ /// <inheritdoc />
+ public IReadOnlyList<TaskTriggerInfo> Triggers
+ {
+ get
{
- get
- {
- return Array.ConvertAll(InternalTriggers, i => i.Item1);
- }
+ return Array.ConvertAll(InternalTriggers, i => i.Item1);
+ }
- set
- {
- ArgumentNullException.ThrowIfNull(value);
+ set
+ {
+ ArgumentNullException.ThrowIfNull(value);
- // This null check is not great, but is needed to handle bad user input, or user mucking with the config file incorrectly
- var triggerList = value.Where(i => i is not null).ToArray();
+ // This null check is not great, but is needed to handle bad user input, or user mucking with the config file incorrectly
+ var triggerList = value.Where(i => i is not null).ToArray();
- SaveTriggers(triggerList);
+ SaveTriggers(triggerList);
- InternalTriggers = Array.ConvertAll(triggerList, i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i)));
- }
+ InternalTriggers = Array.ConvertAll(triggerList, i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i)));
}
+ }
- /// <inheritdoc />
- public string Id
+ /// <inheritdoc />
+ public string Id
+ {
+ get
{
- get
- {
- return _id ??= ScheduledTask.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture);
- }
+ return _id ??= ScheduledTask.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture);
}
+ }
- private void InitTriggerEvents()
- {
- _triggers = LoadTriggers();
- ReloadTriggerEvents(true);
- }
+ private void InitTriggerEvents()
+ {
+ _triggers = LoadTriggers();
+ ReloadTriggerEvents(true);
+ }
- /// <inheritdoc />
- public void ReloadTriggerEvents()
- {
- ReloadTriggerEvents(false);
- }
+ /// <inheritdoc />
+ public void ReloadTriggerEvents()
+ {
+ ReloadTriggerEvents(false);
+ }
- /// <summary>
- /// Reloads the trigger events.
- /// </summary>
- /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
- private void ReloadTriggerEvents(bool isApplicationStartup)
+ /// <summary>
+ /// Reloads the trigger events.
+ /// </summary>
+ /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
+ private void ReloadTriggerEvents(bool isApplicationStartup)
+ {
+ foreach (var triggerInfo in InternalTriggers)
{
- foreach (var triggerInfo in InternalTriggers)
- {
- var trigger = triggerInfo.Item2;
+ var trigger = triggerInfo.Item2;
- trigger.Stop();
+ trigger.Stop();
- trigger.Triggered -= OnTriggerTriggered;
- trigger.Triggered += OnTriggerTriggered;
- trigger.Start(LastExecutionResult, _logger, Name, isApplicationStartup);
- }
+ trigger.Triggered -= OnTriggerTriggered;
+ trigger.Triggered += OnTriggerTriggered;
+ trigger.Start(LastExecutionResult, _logger, Name, isApplicationStartup);
}
+ }
- /// <summary>
- /// Handles the Triggered event of the trigger control.
- /// </summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
- private async void OnTriggerTriggered(object sender, EventArgs e)
- {
- var trigger = (ITaskTrigger)sender;
+ /// <summary>
+ /// Handles the Triggered event of the trigger control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
+ private async void OnTriggerTriggered(object sender, EventArgs e)
+ {
+ var trigger = (ITaskTrigger)sender;
- if (ScheduledTask is IConfigurableScheduledTask configurableTask && !configurableTask.IsEnabled)
- {
- return;
- }
+ if (ScheduledTask is IConfigurableScheduledTask configurableTask && !configurableTask.IsEnabled)
+ {
+ return;
+ }
- _logger.LogDebug("{0} fired for task: {1}", trigger.GetType().Name, Name);
+ _logger.LogDebug("{0} fired for task: {1}", trigger.GetType().Name, Name);
- trigger.Stop();
+ trigger.Stop();
- _taskManager.QueueScheduledTask(ScheduledTask, trigger.TaskOptions);
+ _taskManager.QueueScheduledTask(ScheduledTask, trigger.TaskOptions);
- await Task.Delay(1000).ConfigureAwait(false);
+ await Task.Delay(1000).ConfigureAwait(false);
- trigger.Start(LastExecutionResult, _logger, Name, false);
- }
+ trigger.Start(LastExecutionResult, _logger, Name, false);
+ }
- /// <summary>
- /// Executes the task.
- /// </summary>
- /// <param name="options">Task options.</param>
- /// <returns>Task.</returns>
- /// <exception cref="InvalidOperationException">Cannot execute a Task that is already running.</exception>
- public async Task Execute(TaskOptions options)
- {
- var task = Task.Run(async () => await ExecuteInternal(options).ConfigureAwait(false));
+ /// <summary>
+ /// Executes the task.
+ /// </summary>
+ /// <param name="options">Task options.</param>
+ /// <returns>Task.</returns>
+ /// <exception cref="InvalidOperationException">Cannot execute a Task that is already running.</exception>
+ public async Task Execute(TaskOptions options)
+ {
+ var task = Task.Run(async () => await ExecuteInternal(options).ConfigureAwait(false));
- _currentTask = task;
+ _currentTask = task;
- try
- {
- await task.ConfigureAwait(false);
- }
- finally
- {
- _currentTask = null;
- GC.Collect();
- }
+ try
+ {
+ await task.ConfigureAwait(false);
}
-
- private async Task ExecuteInternal(TaskOptions options)
+ finally
{
- // Cancel the current execution, if any
- if (CurrentCancellationTokenSource is not null)
- {
- throw new InvalidOperationException("Cannot execute a Task that is already running");
- }
-
- var progress = new Progress<double>();
+ _currentTask = null;
+ GC.Collect();
+ }
+ }
- CurrentCancellationTokenSource = new CancellationTokenSource();
+ private async Task ExecuteInternal(TaskOptions options)
+ {
+ // Cancel the current execution, if any
+ if (CurrentCancellationTokenSource is not null)
+ {
+ throw new InvalidOperationException("Cannot execute a Task that is already running");
+ }
- _logger.LogDebug("Executing {0}", Name);
+ var progress = new Progress<double>();
- ((TaskManager)_taskManager).OnTaskExecuting(this);
+ CurrentCancellationTokenSource = new CancellationTokenSource();
- progress.ProgressChanged += OnProgressChanged;
+ _logger.LogDebug("Executing {0}", Name);
- TaskCompletionStatus status;
- CurrentExecutionStartTime = DateTime.UtcNow;
+ ((TaskManager)_taskManager).OnTaskExecuting(this);
- Exception failureException = null;
+ progress.ProgressChanged += OnProgressChanged;
- try
- {
- if (options is not null && options.MaxRuntimeTicks.HasValue)
- {
- CurrentCancellationTokenSource.CancelAfter(TimeSpan.FromTicks(options.MaxRuntimeTicks.Value));
- }
+ TaskCompletionStatus status;
+ CurrentExecutionStartTime = DateTime.UtcNow;
- await ScheduledTask.ExecuteAsync(progress, CurrentCancellationTokenSource.Token).ConfigureAwait(false);
+ Exception failureException = null;
- status = TaskCompletionStatus.Completed;
- }
- catch (OperationCanceledException)
+ try
+ {
+ if (options is not null && options.MaxRuntimeTicks.HasValue)
{
- status = TaskCompletionStatus.Cancelled;
+ CurrentCancellationTokenSource.CancelAfter(TimeSpan.FromTicks(options.MaxRuntimeTicks.Value));
}
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error executing Scheduled Task");
- failureException = ex;
-
- status = TaskCompletionStatus.Failed;
- }
+ await ScheduledTask.ExecuteAsync(progress, CurrentCancellationTokenSource.Token).ConfigureAwait(false);
- var startTime = CurrentExecutionStartTime;
- var endTime = DateTime.UtcNow;
+ status = TaskCompletionStatus.Completed;
+ }
+ catch (OperationCanceledException)
+ {
+ status = TaskCompletionStatus.Cancelled;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error executing Scheduled Task");
- progress.ProgressChanged -= OnProgressChanged;
- CurrentCancellationTokenSource.Dispose();
- CurrentCancellationTokenSource = null;
- CurrentProgress = null;
+ failureException = ex;
- OnTaskCompleted(startTime, endTime, status, failureException);
+ status = TaskCompletionStatus.Failed;
}
- /// <summary>
- /// Progress_s the progress changed.
- /// </summary>
- /// <param name="sender">The sender.</param>
- /// <param name="e">The e.</param>
- private void OnProgressChanged(object sender, double e)
- {
- e = Math.Min(e, 100);
+ var startTime = CurrentExecutionStartTime;
+ var endTime = DateTime.UtcNow;
- CurrentProgress = e;
+ progress.ProgressChanged -= OnProgressChanged;
+ CurrentCancellationTokenSource.Dispose();
+ CurrentCancellationTokenSource = null;
+ CurrentProgress = null;
- TaskProgress?.Invoke(this, new GenericEventArgs<double>(e));
- }
+ OnTaskCompleted(startTime, endTime, status, failureException);
+ }
- /// <summary>
- /// Stops the task if it is currently executing.
- /// </summary>
- /// <exception cref="InvalidOperationException">Cannot cancel a Task unless it is in the Running state.</exception>
- public void Cancel()
- {
- if (State != TaskState.Running)
- {
- throw new InvalidOperationException("Cannot cancel a Task unless it is in the Running state.");
- }
+ /// <summary>
+ /// Progress_s the progress changed.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The e.</param>
+ private void OnProgressChanged(object sender, double e)
+ {
+ e = Math.Min(e, 100);
- CancelIfRunning();
- }
+ CurrentProgress = e;
- /// <summary>
- /// Cancels if running.
- /// </summary>
- public void CancelIfRunning()
- {
- if (State == TaskState.Running)
- {
- _logger.LogInformation("Attempting to cancel Scheduled Task {0}", Name);
- CurrentCancellationTokenSource.Cancel();
- }
- }
+ TaskProgress?.Invoke(this, new GenericEventArgs<double>(e));
+ }
- /// <summary>
- /// Gets the scheduled tasks configuration directory.
- /// </summary>
- /// <returns>System.String.</returns>
- private string GetScheduledTasksConfigurationDirectory()
+ /// <summary>
+ /// Stops the task if it is currently executing.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">Cannot cancel a Task unless it is in the Running state.</exception>
+ public void Cancel()
+ {
+ if (State != TaskState.Running)
{
- return Path.Combine(_applicationPaths.ConfigurationDirectoryPath, "ScheduledTasks");
+ throw new InvalidOperationException("Cannot cancel a Task unless it is in the Running state.");
}
- /// <summary>
- /// Gets the scheduled tasks data directory.
- /// </summary>
- /// <returns>System.String.</returns>
- private string GetScheduledTasksDataDirectory()
- {
- return Path.Combine(_applicationPaths.DataPath, "ScheduledTasks");
- }
+ CancelIfRunning();
+ }
- /// <summary>
- /// Gets the history file path.
- /// </summary>
- /// <value>The history file path.</value>
- private string GetHistoryFilePath()
+ /// <summary>
+ /// Cancels if running.
+ /// </summary>
+ public void CancelIfRunning()
+ {
+ if (State == TaskState.Running)
{
- return Path.Combine(GetScheduledTasksDataDirectory(), new Guid(Id) + ".js");
+ _logger.LogInformation("Attempting to cancel Scheduled Task {0}", Name);
+ CurrentCancellationTokenSource.Cancel();
}
+ }
- /// <summary>
- /// Gets the configuration file path.
- /// </summary>
- /// <returns>System.String.</returns>
- private string GetConfigurationFilePath()
- {
- return Path.Combine(GetScheduledTasksConfigurationDirectory(), new Guid(Id) + ".js");
- }
+ /// <summary>
+ /// Gets the scheduled tasks configuration directory.
+ /// </summary>
+ /// <returns>System.String.</returns>
+ private string GetScheduledTasksConfigurationDirectory()
+ {
+ return Path.Combine(_applicationPaths.ConfigurationDirectoryPath, "ScheduledTasks");
+ }
- /// <summary>
- /// Loads the triggers.
- /// </summary>
- /// <returns>IEnumerable{BaseTaskTrigger}.</returns>
- private Tuple<TaskTriggerInfo, ITaskTrigger>[] LoadTriggers()
- {
- // This null check is not great, but is needed to handle bad user input, or user mucking with the config file incorrectly
- var settings = LoadTriggerSettings().Where(i => i is not null);
+ /// <summary>
+ /// Gets the scheduled tasks data directory.
+ /// </summary>
+ /// <returns>System.String.</returns>
+ private string GetScheduledTasksDataDirectory()
+ {
+ return Path.Combine(_applicationPaths.DataPath, "ScheduledTasks");
+ }
- return settings.Select(i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i))).ToArray();
- }
+ /// <summary>
+ /// Gets the history file path.
+ /// </summary>
+ /// <value>The history file path.</value>
+ private string GetHistoryFilePath()
+ {
+ return Path.Combine(GetScheduledTasksDataDirectory(), new Guid(Id) + ".js");
+ }
- private TaskTriggerInfo[] LoadTriggerSettings()
- {
- string path = GetConfigurationFilePath();
- TaskTriggerInfo[] list = null;
- if (File.Exists(path))
- {
- var bytes = File.ReadAllBytes(path);
- list = JsonSerializer.Deserialize<TaskTriggerInfo[]>(bytes, _jsonOptions);
- }
+ /// <summary>
+ /// Gets the configuration file path.
+ /// </summary>
+ /// <returns>System.String.</returns>
+ private string GetConfigurationFilePath()
+ {
+ return Path.Combine(GetScheduledTasksConfigurationDirectory(), new Guid(Id) + ".js");
+ }
- // Return defaults if file doesn't exist.
- return list ?? GetDefaultTriggers();
- }
+ /// <summary>
+ /// Loads the triggers.
+ /// </summary>
+ /// <returns>IEnumerable{BaseTaskTrigger}.</returns>
+ private Tuple<TaskTriggerInfo, ITaskTrigger>[] LoadTriggers()
+ {
+ // This null check is not great, but is needed to handle bad user input, or user mucking with the config file incorrectly
+ var settings = LoadTriggerSettings().Where(i => i is not null);
+
+ return settings.Select(i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i))).ToArray();
+ }
- private TaskTriggerInfo[] GetDefaultTriggers()
+ private TaskTriggerInfo[] LoadTriggerSettings()
+ {
+ string path = GetConfigurationFilePath();
+ TaskTriggerInfo[] list = null;
+ if (File.Exists(path))
{
- try
- {
- return ScheduledTask.GetDefaultTriggers().ToArray();
- }
- catch
- {
- return
- [
- new()
- {
- IntervalTicks = TimeSpan.FromDays(1).Ticks,
- Type = TaskTriggerInfoType.IntervalTrigger
- }
- ];
- }
+ var bytes = File.ReadAllBytes(path);
+ list = JsonSerializer.Deserialize<TaskTriggerInfo[]>(bytes, _jsonOptions);
}
- /// <summary>
- /// Saves the triggers.
- /// </summary>
- /// <param name="triggers">The triggers.</param>
- private void SaveTriggers(TaskTriggerInfo[] triggers)
- {
- var path = GetConfigurationFilePath();
+ // Return defaults if file doesn't exist.
+ return list ?? GetDefaultTriggers();
+ }
- Directory.CreateDirectory(Path.GetDirectoryName(path));
- using FileStream createStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
- using Utf8JsonWriter jsonWriter = new Utf8JsonWriter(createStream);
- JsonSerializer.Serialize(jsonWriter, triggers, _jsonOptions);
+ private TaskTriggerInfo[] GetDefaultTriggers()
+ {
+ try
+ {
+ return ScheduledTask.GetDefaultTriggers().ToArray();
}
-
- /// <summary>
- /// Called when [task completed].
- /// </summary>
- /// <param name="startTime">The start time.</param>
- /// <param name="endTime">The end time.</param>
- /// <param name="status">The status.</param>
- /// <param name="ex">The exception.</param>
- private void OnTaskCompleted(DateTime startTime, DateTime endTime, TaskCompletionStatus status, Exception ex)
+ catch
{
- var elapsedTime = endTime - startTime;
+ return
+ [
+ new()
+ {
+ IntervalTicks = TimeSpan.FromDays(1).Ticks,
+ Type = TaskTriggerInfoType.IntervalTrigger
+ }
+ ];
+ }
+ }
- _logger.LogInformation("{0} {1} after {2} minute(s) and {3} seconds", Name, status, Math.Truncate(elapsedTime.TotalMinutes), elapsedTime.Seconds);
+ /// <summary>
+ /// Saves the triggers.
+ /// </summary>
+ /// <param name="triggers">The triggers.</param>
+ private void SaveTriggers(TaskTriggerInfo[] triggers)
+ {
+ var path = GetConfigurationFilePath();
- var result = new TaskResult
- {
- StartTimeUtc = startTime,
- EndTimeUtc = endTime,
- Status = status,
- Name = Name,
- Id = Id
- };
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+ using FileStream createStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
+ using Utf8JsonWriter jsonWriter = new Utf8JsonWriter(createStream);
+ JsonSerializer.Serialize(jsonWriter, triggers, _jsonOptions);
+ }
- result.Key = ScheduledTask.Key;
+ /// <summary>
+ /// Called when [task completed].
+ /// </summary>
+ /// <param name="startTime">The start time.</param>
+ /// <param name="endTime">The end time.</param>
+ /// <param name="status">The status.</param>
+ /// <param name="ex">The exception.</param>
+ private void OnTaskCompleted(DateTime startTime, DateTime endTime, TaskCompletionStatus status, Exception ex)
+ {
+ var elapsedTime = endTime - startTime;
- if (ex is not null)
- {
- result.ErrorMessage = ex.Message;
- result.LongErrorMessage = ex.StackTrace;
- }
+ _logger.LogInformation("{0} {1} after {2} minute(s) and {3} seconds", Name, status, Math.Truncate(elapsedTime.TotalMinutes), elapsedTime.Seconds);
- LastExecutionResult = result;
+ var result = new TaskResult
+ {
+ StartTimeUtc = startTime,
+ EndTimeUtc = endTime,
+ Status = status,
+ Name = Name,
+ Id = Id
+ };
- ((TaskManager)_taskManager).OnTaskCompleted(this, result);
- }
+ result.Key = ScheduledTask.Key;
- /// <inheritdoc />
- public void Dispose()
+ if (ex is not null)
{
- Dispose(true);
- GC.SuppressFinalize(this);
+ result.ErrorMessage = ex.Message;
+ result.LongErrorMessage = ex.StackTrace;
}
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources.
- /// </summary>
- /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool dispose)
+ LastExecutionResult = result;
+
+ ((TaskManager)_taskManager).OnTaskCompleted(this, result);
+ }
+
+ /// <inheritdoc />
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Releases unmanaged and - optionally - managed resources.
+ /// </summary>
+ /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+ protected virtual void Dispose(bool dispose)
+ {
+ if (dispose)
{
- if (dispose)
- {
- DisposeTriggers();
+ DisposeTriggers();
- var wasRunning = State == TaskState.Running;
- var startTime = CurrentExecutionStartTime;
+ var wasRunning = State == TaskState.Running;
+ var startTime = CurrentExecutionStartTime;
- var token = CurrentCancellationTokenSource;
- if (token is not null)
+ var token = CurrentCancellationTokenSource;
+ if (token is not null)
+ {
+ try
{
- try
- {
- _logger.LogInformation("{Name}: Cancelling", Name);
- token.Cancel();
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error calling CancellationToken.Cancel();");
- }
+ _logger.LogInformation("{Name}: Cancelling", Name);
+ token.Cancel();
}
-
- var task = _currentTask;
- if (task is not null)
+ catch (Exception ex)
{
- try
- {
- _logger.LogInformation("{Name}: Waiting on Task", Name);
- var exited = task.Wait(2000);
-
- if (exited)
- {
- _logger.LogInformation("{Name}: Task exited", Name);
- }
- else
- {
- _logger.LogInformation("{Name}: Timed out waiting for task to stop", Name);
- }
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error calling Task.WaitAll();");
- }
+ _logger.LogError(ex, "Error calling CancellationToken.Cancel();");
}
+ }
- if (token is not null)
+ var task = _currentTask;
+ if (task is not null)
+ {
+ try
{
- try
+ _logger.LogInformation("{Name}: Waiting on Task", Name);
+ var exited = task.Wait(2000);
+
+ if (exited)
{
- _logger.LogDebug("{Name}: Disposing CancellationToken", Name);
- token.Dispose();
+ _logger.LogInformation("{Name}: Task exited", Name);
}
- catch (Exception ex)
+ else
{
- _logger.LogError(ex, "Error calling CancellationToken.Dispose();");
+ _logger.LogInformation("{Name}: Timed out waiting for task to stop", Name);
}
}
-
- if (wasRunning)
+ catch (Exception ex)
{
- OnTaskCompleted(startTime, DateTime.UtcNow, TaskCompletionStatus.Aborted, null);
+ _logger.LogError(ex, "Error calling Task.WaitAll();");
}
}
- }
-
- /// <summary>
- /// Converts a TaskTriggerInfo into a concrete BaseTaskTrigger.
- /// </summary>
- /// <param name="info">The info.</param>
- /// <returns>BaseTaskTrigger.</returns>
- /// <exception cref="ArgumentException">Invalid trigger type: + info.Type.</exception>
- private ITaskTrigger GetTrigger(TaskTriggerInfo info)
- {
- var options = new TaskOptions
- {
- MaxRuntimeTicks = info.MaxRuntimeTicks
- };
- if (info.Type == TaskTriggerInfoType.DailyTrigger)
+ if (token is not null)
{
- if (!info.TimeOfDayTicks.HasValue)
+ try
{
- throw new ArgumentException("Info did not contain a TimeOfDayTicks.", nameof(info));
+ _logger.LogDebug("{Name}: Disposing CancellationToken", Name);
+ token.Dispose();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error calling CancellationToken.Dispose();");
}
-
- return new DailyTrigger(TimeSpan.FromTicks(info.TimeOfDayTicks.Value), options);
}
- if (info.Type == TaskTriggerInfoType.WeeklyTrigger)
+ if (wasRunning)
{
- if (!info.TimeOfDayTicks.HasValue)
- {
- throw new ArgumentException("Info did not contain a TimeOfDayTicks.", nameof(info));
- }
+ OnTaskCompleted(startTime, DateTime.UtcNow, TaskCompletionStatus.Aborted, null);
+ }
+ }
+ }
- if (!info.DayOfWeek.HasValue)
- {
- throw new ArgumentException("Info did not contain a DayOfWeek.", nameof(info));
- }
+ /// <summary>
+ /// Converts a TaskTriggerInfo into a concrete BaseTaskTrigger.
+ /// </summary>
+ /// <param name="info">The info.</param>
+ /// <returns>BaseTaskTrigger.</returns>
+ /// <exception cref="ArgumentException">Invalid trigger type: + info.Type.</exception>
+ private ITaskTrigger GetTrigger(TaskTriggerInfo info)
+ {
+ var options = new TaskOptions
+ {
+ MaxRuntimeTicks = info.MaxRuntimeTicks
+ };
- return new WeeklyTrigger(TimeSpan.FromTicks(info.TimeOfDayTicks.Value), info.DayOfWeek.Value, options);
+ if (info.Type == TaskTriggerInfoType.DailyTrigger)
+ {
+ if (!info.TimeOfDayTicks.HasValue)
+ {
+ throw new ArgumentException("Info did not contain a TimeOfDayTicks.", nameof(info));
}
- if (info.Type == TaskTriggerInfoType.IntervalTrigger)
+ return new DailyTrigger(TimeSpan.FromTicks(info.TimeOfDayTicks.Value), options);
+ }
+
+ if (info.Type == TaskTriggerInfoType.WeeklyTrigger)
+ {
+ if (!info.TimeOfDayTicks.HasValue)
{
- if (!info.IntervalTicks.HasValue)
- {
- throw new ArgumentException("Info did not contain a IntervalTicks.", nameof(info));
- }
+ throw new ArgumentException("Info did not contain a TimeOfDayTicks.", nameof(info));
+ }
- return new IntervalTrigger(TimeSpan.FromTicks(info.IntervalTicks.Value), options);
+ if (!info.DayOfWeek.HasValue)
+ {
+ throw new ArgumentException("Info did not contain a DayOfWeek.", nameof(info));
}
- if (info.Type == TaskTriggerInfoType.StartupTrigger)
+ return new WeeklyTrigger(TimeSpan.FromTicks(info.TimeOfDayTicks.Value), info.DayOfWeek.Value, options);
+ }
+
+ if (info.Type == TaskTriggerInfoType.IntervalTrigger)
+ {
+ if (!info.IntervalTicks.HasValue)
{
- return new StartupTrigger(options);
+ throw new ArgumentException("Info did not contain a IntervalTicks.", nameof(info));
}
- throw new ArgumentException("Unrecognized trigger type: " + info.Type);
+ return new IntervalTrigger(TimeSpan.FromTicks(info.IntervalTicks.Value), options);
}
- /// <summary>
- /// Disposes each trigger.
- /// </summary>
- private void DisposeTriggers()
+ if (info.Type == TaskTriggerInfoType.StartupTrigger)
{
- foreach (var triggerInfo in InternalTriggers)
+ return new StartupTrigger(options);
+ }
+
+ throw new ArgumentException("Unrecognized trigger type: " + info.Type);
+ }
+
+ /// <summary>
+ /// Disposes each trigger.
+ /// </summary>
+ private void DisposeTriggers()
+ {
+ foreach (var triggerInfo in InternalTriggers)
+ {
+ var trigger = triggerInfo.Item2;
+ trigger.Triggered -= OnTriggerTriggered;
+ trigger.Stop();
+ if (trigger is IDisposable disposable)
{
- var trigger = triggerInfo.Item2;
- trigger.Triggered -= OnTriggerTriggered;
- trigger.Stop();
- if (trigger is IDisposable disposable)
- {
- disposable.Dispose();
- }
+ disposable.Dispose();
}
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs
index a5e4104ff..4ec2c9c78 100644
--- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs
@@ -8,255 +8,254 @@ using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
-namespace Emby.Server.Implementations.ScheduledTasks
+namespace Emby.Server.Implementations.ScheduledTasks;
+
+/// <summary>
+/// Class TaskManager.
+/// </summary>
+public class TaskManager : ITaskManager
{
/// <summary>
- /// Class TaskManager.
+ /// The _task queue.
/// </summary>
- public class TaskManager : ITaskManager
- {
- /// <summary>
- /// The _task queue.
- /// </summary>
- private readonly ConcurrentQueue<Tuple<Type, TaskOptions>> _taskQueue =
- new ConcurrentQueue<Tuple<Type, TaskOptions>>();
-
- private readonly IApplicationPaths _applicationPaths;
- private readonly ILogger<TaskManager> _logger;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="TaskManager" /> class.
- /// </summary>
- /// <param name="applicationPaths">The application paths.</param>
- /// <param name="logger">The logger.</param>
- public TaskManager(
- IApplicationPaths applicationPaths,
- ILogger<TaskManager> logger)
- {
- _applicationPaths = applicationPaths;
- _logger = logger;
+ private readonly ConcurrentQueue<Tuple<Type, TaskOptions>> _taskQueue =
+ new ConcurrentQueue<Tuple<Type, TaskOptions>>();
- ScheduledTasks = Array.Empty<IScheduledTaskWorker>();
- }
+ private readonly IApplicationPaths _applicationPaths;
+ private readonly ILogger<TaskManager> _logger;
- /// <inheritdoc />
- public event EventHandler<GenericEventArgs<IScheduledTaskWorker>>? TaskExecuting;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TaskManager" /> class.
+ /// </summary>
+ /// <param name="applicationPaths">The application paths.</param>
+ /// <param name="logger">The logger.</param>
+ public TaskManager(
+ IApplicationPaths applicationPaths,
+ ILogger<TaskManager> logger)
+ {
+ _applicationPaths = applicationPaths;
+ _logger = logger;
- /// <inheritdoc />
- public event EventHandler<TaskCompletionEventArgs>? TaskCompleted;
+ ScheduledTasks = [];
+ }
- /// <inheritdoc />
- public IReadOnlyList<IScheduledTaskWorker> ScheduledTasks { get; private set; }
+ /// <inheritdoc />
+ public event EventHandler<GenericEventArgs<IScheduledTaskWorker>>? TaskExecuting;
- /// <inheritdoc />
- public void CancelIfRunningAndQueue<T>(TaskOptions options)
- where T : IScheduledTask
- {
- var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
- ((ScheduledTaskWorker)task).CancelIfRunning();
+ /// <inheritdoc />
+ public event EventHandler<TaskCompletionEventArgs>? TaskCompleted;
- QueueScheduledTask<T>(options);
- }
+ /// <inheritdoc />
+ public IReadOnlyList<IScheduledTaskWorker> ScheduledTasks { get; private set; }
- /// <inheritdoc />
- public void CancelIfRunningAndQueue<T>()
- where T : IScheduledTask
- {
- CancelIfRunningAndQueue<T>(new TaskOptions());
- }
+ /// <inheritdoc />
+ public void CancelIfRunningAndQueue<T>(TaskOptions options)
+ where T : IScheduledTask
+ {
+ var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
+ ((ScheduledTaskWorker)task).CancelIfRunning();
- /// <inheritdoc />
- public void CancelIfRunning<T>()
- where T : IScheduledTask
- {
- var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
- ((ScheduledTaskWorker)task).CancelIfRunning();
- }
+ QueueScheduledTask<T>(options);
+ }
- /// <inheritdoc />
- public void QueueScheduledTask<T>(TaskOptions options)
+ /// <inheritdoc />
+ public void CancelIfRunningAndQueue<T>()
where T : IScheduledTask
- {
- var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == typeof(T));
+ {
+ CancelIfRunningAndQueue<T>(new TaskOptions());
+ }
- if (scheduledTask is null)
- {
- _logger.LogError("Unable to find scheduled task of type {0} in QueueScheduledTask.", typeof(T).Name);
- }
- else
- {
- QueueScheduledTask(scheduledTask, options);
- }
- }
+ /// <inheritdoc />
+ public void CancelIfRunning<T>()
+ where T : IScheduledTask
+ {
+ var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
+ ((ScheduledTaskWorker)task).CancelIfRunning();
+ }
- /// <inheritdoc />
- public void QueueScheduledTask<T>()
- where T : IScheduledTask
- {
- QueueScheduledTask<T>(new TaskOptions());
- }
+ /// <inheritdoc />
+ public void QueueScheduledTask<T>(TaskOptions options)
+ where T : IScheduledTask
+ {
+ var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == typeof(T));
- /// <inheritdoc />
- public void QueueIfNotRunning<T>()
- where T : IScheduledTask
+ if (scheduledTask is null)
{
- var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
-
- if (task.State != TaskState.Running)
- {
- QueueScheduledTask<T>(new TaskOptions());
- }
+ _logger.LogError("Unable to find scheduled task of type {Type} in QueueScheduledTask.", typeof(T).Name);
}
-
- /// <inheritdoc />
- public void Execute<T>()
- where T : IScheduledTask
+ else
{
- var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == typeof(T));
+ QueueScheduledTask(scheduledTask, options);
+ }
+ }
- if (scheduledTask is null)
- {
- _logger.LogError("Unable to find scheduled task of type {0} in Execute.", typeof(T).Name);
- }
- else
- {
- var type = scheduledTask.ScheduledTask.GetType();
+ /// <inheritdoc />
+ public void QueueScheduledTask<T>()
+ where T : IScheduledTask
+ {
+ QueueScheduledTask<T>(new TaskOptions());
+ }
- _logger.LogDebug("Queuing task {0}", type.Name);
+ /// <inheritdoc />
+ public void QueueIfNotRunning<T>()
+ where T : IScheduledTask
+ {
+ var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
- lock (_taskQueue)
- {
- if (scheduledTask.State == TaskState.Idle)
- {
- Execute(scheduledTask, new TaskOptions());
- }
- }
- }
+ if (task.State != TaskState.Running)
+ {
+ QueueScheduledTask<T>(new TaskOptions());
}
+ }
- /// <inheritdoc />
- public void QueueScheduledTask(IScheduledTask task, TaskOptions options)
- {
- var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == task.GetType());
+ /// <inheritdoc />
+ public void Execute<T>()
+ where T : IScheduledTask
+ {
+ var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == typeof(T));
- if (scheduledTask is null)
- {
- _logger.LogError("Unable to find scheduled task of type {0} in QueueScheduledTask.", task.GetType().Name);
- }
- else
- {
- QueueScheduledTask(scheduledTask, options);
- }
+ if (scheduledTask is null)
+ {
+ _logger.LogError("Unable to find scheduled task of type {Type} in Execute.", typeof(T).Name);
}
-
- /// <summary>
- /// Queues the scheduled task.
- /// </summary>
- /// <param name="task">The task.</param>
- /// <param name="options">The task options.</param>
- private void QueueScheduledTask(IScheduledTaskWorker task, TaskOptions options)
+ else
{
- var type = task.ScheduledTask.GetType();
+ var type = scheduledTask.ScheduledTask.GetType();
- _logger.LogDebug("Queuing task {0}", type.Name);
+ _logger.LogDebug("Queuing task {Name}", type.Name);
lock (_taskQueue)
{
- if (task.State == TaskState.Idle)
+ if (scheduledTask.State == TaskState.Idle)
{
- Execute(task, options);
- return;
+ Execute(scheduledTask, new TaskOptions());
}
-
- _taskQueue.Enqueue(new Tuple<Type, TaskOptions>(type, options));
}
}
+ }
- /// <inheritdoc />
- public void AddTasks(IEnumerable<IScheduledTask> tasks)
- {
- var list = tasks.Select(t => new ScheduledTaskWorker(t, _applicationPaths, this, _logger));
+ /// <inheritdoc />
+ public void QueueScheduledTask(IScheduledTask task, TaskOptions options)
+ {
+ var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == task.GetType());
- ScheduledTasks = ScheduledTasks.Concat(list).ToArray();
+ if (scheduledTask is null)
+ {
+ _logger.LogError("Unable to find scheduled task of type {Type} in QueueScheduledTask.", task.GetType().Name);
}
-
- /// <inheritdoc />
- public void Dispose()
+ else
{
- Dispose(true);
- GC.SuppressFinalize(this);
+ QueueScheduledTask(scheduledTask, options);
}
+ }
+
+ /// <summary>
+ /// Queues the scheduled task.
+ /// </summary>
+ /// <param name="task">The task.</param>
+ /// <param name="options">The task options.</param>
+ private void QueueScheduledTask(IScheduledTaskWorker task, TaskOptions options)
+ {
+ var type = task.ScheduledTask.GetType();
+
+ _logger.LogDebug("Queuing task {Name}", type.Name);
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources.
- /// </summary>
- /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool dispose)
+ lock (_taskQueue)
{
- foreach (var task in ScheduledTasks)
+ if (task.State == TaskState.Idle)
{
- task.Dispose();
+ Execute(task, options);
+ return;
}
- }
- /// <inheritdoc />
- public void Cancel(IScheduledTaskWorker task)
- {
- ((ScheduledTaskWorker)task).Cancel();
+ _taskQueue.Enqueue(new Tuple<Type, TaskOptions>(type, options));
}
+ }
- /// <inheritdoc />
- public Task Execute(IScheduledTaskWorker task, TaskOptions options)
- {
- return ((ScheduledTaskWorker)task).Execute(options);
- }
+ /// <inheritdoc />
+ public void AddTasks(IEnumerable<IScheduledTask> tasks)
+ {
+ var list = tasks.Select(t => new ScheduledTaskWorker(t, _applicationPaths, this, _logger));
+
+ ScheduledTasks = ScheduledTasks.Concat(list).ToArray();
+ }
+
+ /// <inheritdoc />
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
- /// <summary>
- /// Called when [task executing].
- /// </summary>
- /// <param name="task">The task.</param>
- internal void OnTaskExecuting(IScheduledTaskWorker task)
+ /// <summary>
+ /// Releases unmanaged and - optionally - managed resources.
+ /// </summary>
+ /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+ protected virtual void Dispose(bool dispose)
+ {
+ foreach (var task in ScheduledTasks)
{
- TaskExecuting?.Invoke(this, new GenericEventArgs<IScheduledTaskWorker>(task));
+ task.Dispose();
}
+ }
- /// <summary>
- /// Called when [task completed].
- /// </summary>
- /// <param name="task">The task.</param>
- /// <param name="result">The result.</param>
- internal void OnTaskCompleted(IScheduledTaskWorker task, TaskResult result)
- {
- TaskCompleted?.Invoke(task, new TaskCompletionEventArgs(task, result));
+ /// <inheritdoc />
+ public void Cancel(IScheduledTaskWorker task)
+ {
+ ((ScheduledTaskWorker)task).Cancel();
+ }
- ExecuteQueuedTasks();
- }
+ /// <inheritdoc />
+ public Task Execute(IScheduledTaskWorker task, TaskOptions options)
+ {
+ return ((ScheduledTaskWorker)task).Execute(options);
+ }
+
+ /// <summary>
+ /// Called when [task executing].
+ /// </summary>
+ /// <param name="task">The task.</param>
+ internal void OnTaskExecuting(IScheduledTaskWorker task)
+ {
+ TaskExecuting?.Invoke(this, new GenericEventArgs<IScheduledTaskWorker>(task));
+ }
+
+ /// <summary>
+ /// Called when [task completed].
+ /// </summary>
+ /// <param name="task">The task.</param>
+ /// <param name="result">The result.</param>
+ internal void OnTaskCompleted(IScheduledTaskWorker task, TaskResult result)
+ {
+ TaskCompleted?.Invoke(task, new TaskCompletionEventArgs(task, result));
+
+ ExecuteQueuedTasks();
+ }
- /// <summary>
- /// Executes the queued tasks.
- /// </summary>
- private void ExecuteQueuedTasks()
+ /// <summary>
+ /// Executes the queued tasks.
+ /// </summary>
+ private void ExecuteQueuedTasks()
+ {
+ lock (_taskQueue)
{
- lock (_taskQueue)
- {
- var list = new List<Tuple<Type, TaskOptions>>();
+ var list = new List<Tuple<Type, TaskOptions>>();
- while (_taskQueue.TryDequeue(out var item))
+ while (_taskQueue.TryDequeue(out var item))
+ {
+ if (list.All(i => i.Item1 != item.Item1))
{
- if (list.All(i => i.Item1 != item.Item1))
- {
- list.Add(item);
- }
+ list.Add(item);
}
+ }
- foreach (var enqueuedType in list)
- {
- var scheduledTask = ScheduledTasks.First(t => t.ScheduledTask.GetType() == enqueuedType.Item1);
+ foreach (var enqueuedType in list)
+ {
+ var scheduledTask = ScheduledTasks.First(t => t.ScheduledTask.GetType() == enqueuedType.Item1);
- if (scheduledTask.State == TaskState.Idle)
- {
- Execute(scheduledTask, enqueuedType.Item2);
- }
+ if (scheduledTask.State == TaskState.Idle)
+ {
+ Execute(scheduledTask, enqueuedType.Item2);
}
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs
index 8d1d509ff..ef005bfaa 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs
@@ -156,14 +156,11 @@ public partial class AudioNormalizationTask : IScheduledTask
/// <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, bool waitForExit, CancellationToken cancellationToken)
@@ -194,7 +191,7 @@ public partial class AudioNormalizationTask : IScheduledTask
using var reader = process.StandardError;
float? lufs = null;
- await foreach (var line in reader.ReadAllLinesAsync(cancellationToken))
+ await foreach (var line in reader.ReadAllLinesAsync(cancellationToken).ConfigureAwait(false))
{
Match match = LUFSRegex().Match(line);
if (match.Success)
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
index b76fdeeb0..f81309560 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
@@ -17,155 +17,151 @@ 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 IApplicationPaths _appPaths;
- private readonly IChapterManager _chapterManager;
- private readonly IFileSystem _fileSystem;
- private readonly ILocalizationManager _localization;
-
- /// <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="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)
- {
- _logger = logger;
- _libraryManager = libraryManager;
- _appPaths = appPaths;
- _chapterManager = chapterManager;
- _fileSystem = fileSystem;
- _localization = localization;
- }
+ _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 = [];
- }
+ previouslyFailedImages = (await File.ReadAllTextAsync(failHistoryPath, cancellationToken).ConfigureAwait(false))
+ .Split('|', StringSplitOptions.RemoveEmptyEntries)
+ .ToList();
}
- else
+ catch (IOException)
{
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 = _chapterManager.GetChapters(video.Id);
+ var extract = !previouslyFailedImages.Contains(key, StringComparison.OrdinalIgnoreCase);
- var success = await _chapterManager.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 8901390aa..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 />
@@ -135,6 +131,9 @@ public class CleanupCollectionAndPlaylistPathsTask : IScheduledTask
/// <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/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..b8c944d3d 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs
@@ -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
};
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs
index 4d3a04377..bf8ffaf47 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs
@@ -5,84 +5,78 @@ using System.Threading.Tasks;
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;
- private readonly IJellyfinDatabaseProvider _jellyfinDatabaseProvider;
+ _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>
- /// <param name="jellyfinDatabaseProvider">Instance of the JellyfinDatabaseProvider that can be used for provider specific operations.</param>
- public OptimizeDatabaseTask(
- ILogger<OptimizeDatabaseTask> logger,
- ILocalizationManager localization,
- IDbContextFactory<JellyfinDbContext> provider,
- IJellyfinDatabaseProvider jellyfinDatabaseProvider)
- {
- _logger = logger;
- _localization = localization;
- _provider = provider;
- _jellyfinDatabaseProvider = jellyfinDatabaseProvider;
- }
+ /// <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
- {
- await _jellyfinDatabaseProvider.RunScheduledOptimisation(cancellationToken).ConfigureAwait(false);
- }
- 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..c96843199 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 Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
- progress.Report(0);
+ progress.Report(0);
- return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken);
- }
+ return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken);
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs
index 6d2a74da4..9abcd9c7b 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs
@@ -3,85 +3,84 @@ using System.Threading;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
-namespace Emby.Server.Implementations.ScheduledTasks.Triggers
+namespace Emby.Server.Implementations.ScheduledTasks.Triggers;
+
+/// <summary>
+/// Represents a task trigger that fires everyday.
+/// </summary>
+public sealed class DailyTrigger : ITaskTrigger, IDisposable
{
+ private readonly TimeSpan _timeOfDay;
+ private Timer? _timer;
+ private bool _disposed;
+
/// <summary>
- /// Represents a task trigger that fires everyday.
+ /// Initializes a new instance of the <see cref="DailyTrigger"/> class.
/// </summary>
- public sealed class DailyTrigger : ITaskTrigger, IDisposable
+ /// <param name="timeOfDay">The time of day to trigger the task to run.</param>
+ /// <param name="taskOptions">The options of this task.</param>
+ public DailyTrigger(TimeSpan timeOfDay, TaskOptions taskOptions)
{
- private readonly TimeSpan _timeOfDay;
- private Timer? _timer;
- private bool _disposed = false;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="DailyTrigger"/> class.
- /// </summary>
- /// <param name="timeofDay">The time of day to trigger the task to run.</param>
- /// <param name="taskOptions">The options of this task.</param>
- public DailyTrigger(TimeSpan timeofDay, TaskOptions taskOptions)
- {
- _timeOfDay = timeofDay;
- TaskOptions = taskOptions;
- }
+ _timeOfDay = timeOfDay;
+ TaskOptions = taskOptions;
+ }
- /// <inheritdoc />
- public event EventHandler<EventArgs>? Triggered;
+ /// <inheritdoc />
+ public event EventHandler<EventArgs>? Triggered;
- /// <inheritdoc />
- public TaskOptions TaskOptions { get; }
+ /// <inheritdoc />
+ public TaskOptions TaskOptions { get; }
- /// <inheritdoc />
- public void Start(TaskResult? lastResult, ILogger logger, string taskName, bool isApplicationStartup)
- {
- DisposeTimer();
+ /// <inheritdoc />
+ public void Start(TaskResult? lastResult, ILogger logger, string taskName, bool isApplicationStartup)
+ {
+ DisposeTimer();
- var now = DateTime.Now;
+ var now = DateTime.Now;
- var triggerDate = now.TimeOfDay > _timeOfDay ? now.Date.AddDays(1) : now.Date;
- triggerDate = triggerDate.Add(_timeOfDay);
+ var triggerDate = now.TimeOfDay > _timeOfDay ? now.Date.AddDays(1) : now.Date;
+ triggerDate = triggerDate.Add(_timeOfDay);
- var dueTime = triggerDate - now;
+ var dueTime = triggerDate - now;
- logger.LogInformation("Daily trigger for {Task} set to fire at {TriggerDate:yyyy-MM-dd HH:mm:ss.fff zzz}, which is {DueTime:c} from now.", taskName, triggerDate, dueTime);
+ logger.LogInformation("Daily trigger for {Task} set to fire at {TriggerDate:yyyy-MM-dd HH:mm:ss.fff zzz}, which is {DueTime:c} from now.", taskName, triggerDate, dueTime);
- _timer = new Timer(_ => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1));
- }
+ _timer = new Timer(_ => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1));
+ }
- /// <inheritdoc />
- public void Stop()
- {
- DisposeTimer();
- }
+ /// <inheritdoc />
+ public void Stop()
+ {
+ DisposeTimer();
+ }
- /// <summary>
- /// Disposes the timer.
- /// </summary>
- private void DisposeTimer()
- {
- _timer?.Dispose();
- _timer = null;
- }
+ /// <summary>
+ /// Disposes the timer.
+ /// </summary>
+ private void DisposeTimer()
+ {
+ _timer?.Dispose();
+ _timer = null;
+ }
- /// <summary>
- /// Called when [triggered].
- /// </summary>
- private void OnTriggered()
- {
- Triggered?.Invoke(this, EventArgs.Empty);
- }
+ /// <summary>
+ /// Called when [triggered].
+ /// </summary>
+ private void OnTriggered()
+ {
+ Triggered?.Invoke(this, EventArgs.Empty);
+ }
- /// <inheritdoc />
- public void Dispose()
+ /// <inheritdoc />
+ public void Dispose()
+ {
+ if (_disposed)
{
- if (_disposed)
- {
- return;
- }
+ return;
+ }
- DisposeTimer();
+ DisposeTimer();
- _disposed = true;
- }
+ _disposed = true;
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs
index 9425b47d0..d6773b65e 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs
@@ -4,104 +4,103 @@ using System.Threading;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
-namespace Emby.Server.Implementations.ScheduledTasks.Triggers
+namespace Emby.Server.Implementations.ScheduledTasks.Triggers;
+
+/// <summary>
+/// Represents a task trigger that runs repeatedly on an interval.
+/// </summary>
+public sealed class IntervalTrigger : ITaskTrigger, IDisposable
{
+ private readonly TimeSpan _interval;
+ private DateTime _lastStartDate;
+ private Timer? _timer;
+ private bool _disposed;
+
/// <summary>
- /// Represents a task trigger that runs repeatedly on an interval.
+ /// Initializes a new instance of the <see cref="IntervalTrigger"/> class.
/// </summary>
- public sealed class IntervalTrigger : ITaskTrigger, IDisposable
+ /// <param name="interval">The interval.</param>
+ /// <param name="taskOptions">The options of this task.</param>
+ public IntervalTrigger(TimeSpan interval, TaskOptions taskOptions)
{
- private readonly TimeSpan _interval;
- private DateTime _lastStartDate;
- private Timer? _timer;
- private bool _disposed = false;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="IntervalTrigger"/> class.
- /// </summary>
- /// <param name="interval">The interval.</param>
- /// <param name="taskOptions">The options of this task.</param>
- public IntervalTrigger(TimeSpan interval, TaskOptions taskOptions)
- {
- _interval = interval;
- TaskOptions = taskOptions;
- }
+ _interval = interval;
+ TaskOptions = taskOptions;
+ }
+
+ /// <inheritdoc />
+ public event EventHandler<EventArgs>? Triggered;
- /// <inheritdoc />
- public event EventHandler<EventArgs>? Triggered;
+ /// <inheritdoc />
+ public TaskOptions TaskOptions { get; }
+
+ /// <inheritdoc />
+ public void Start(TaskResult? lastResult, ILogger logger, string taskName, bool isApplicationStartup)
+ {
+ DisposeTimer();
- /// <inheritdoc />
- public TaskOptions TaskOptions { get; }
+ DateTime now = DateTime.UtcNow;
+ DateTime triggerDate;
- /// <inheritdoc />
- public void Start(TaskResult? lastResult, ILogger logger, string taskName, bool isApplicationStartup)
+ if (lastResult is null)
{
- DisposeTimer();
-
- DateTime now = DateTime.UtcNow;
- DateTime triggerDate;
-
- if (lastResult is null)
- {
- // Task has never been completed before
- triggerDate = now.AddHours(1);
- }
- else
- {
- triggerDate = new[] { lastResult.EndTimeUtc, _lastStartDate, now.AddMinutes(1) }.Max().Add(_interval);
- }
-
- var dueTime = triggerDate - now;
- var maxDueTime = TimeSpan.FromDays(7);
-
- if (dueTime > maxDueTime)
- {
- dueTime = maxDueTime;
- }
-
- _timer = new Timer(_ => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1));
+ // Task has never been completed before
+ triggerDate = now.AddHours(1);
}
-
- /// <inheritdoc />
- public void Stop()
+ else
{
- DisposeTimer();
+ triggerDate = new[] { lastResult.EndTimeUtc, _lastStartDate, now.AddMinutes(1) }.Max().Add(_interval);
}
- /// <summary>
- /// Disposes the timer.
- /// </summary>
- private void DisposeTimer()
+ var dueTime = triggerDate - now;
+ var maxDueTime = TimeSpan.FromDays(7);
+
+ if (dueTime > maxDueTime)
{
- _timer?.Dispose();
- _timer = null;
+ dueTime = maxDueTime;
}
- /// <summary>
- /// Called when [triggered].
- /// </summary>
- private void OnTriggered()
- {
- DisposeTimer();
+ _timer = new Timer(_ => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1));
+ }
+
+ /// <inheritdoc />
+ public void Stop()
+ {
+ DisposeTimer();
+ }
- if (Triggered is not null)
- {
- _lastStartDate = DateTime.UtcNow;
- Triggered(this, EventArgs.Empty);
- }
+ /// <summary>
+ /// Disposes the timer.
+ /// </summary>
+ private void DisposeTimer()
+ {
+ _timer?.Dispose();
+ _timer = null;
+ }
+
+ /// <summary>
+ /// Called when [triggered].
+ /// </summary>
+ private void OnTriggered()
+ {
+ DisposeTimer();
+
+ if (Triggered is not null)
+ {
+ _lastStartDate = DateTime.UtcNow;
+ Triggered(this, EventArgs.Empty);
}
+ }
- /// <inheritdoc />
- public void Dispose()
+ /// <inheritdoc />
+ public void Dispose()
+ {
+ if (_disposed)
{
- if (_disposed)
- {
- return;
- }
+ return;
+ }
- DisposeTimer();
+ DisposeTimer();
- _disposed = true;
- }
+ _disposed = true;
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs
index 535aa20f9..86ceff6ce 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs
@@ -3,52 +3,51 @@ using System.Threading.Tasks;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
-namespace Emby.Server.Implementations.ScheduledTasks.Triggers
+namespace Emby.Server.Implementations.ScheduledTasks.Triggers;
+
+/// <summary>
+/// Class StartupTaskTrigger.
+/// </summary>
+public sealed class StartupTrigger : ITaskTrigger
{
+ private const int DelayMs = 3000;
+
/// <summary>
- /// Class StartupTaskTrigger.
+ /// Initializes a new instance of the <see cref="StartupTrigger"/> class.
/// </summary>
- public sealed class StartupTrigger : ITaskTrigger
+ /// <param name="taskOptions">The options of this task.</param>
+ public StartupTrigger(TaskOptions taskOptions)
{
- private const int DelayMs = 3000;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="StartupTrigger"/> class.
- /// </summary>
- /// <param name="taskOptions">The options of this task.</param>
- public StartupTrigger(TaskOptions taskOptions)
- {
- TaskOptions = taskOptions;
- }
+ TaskOptions = taskOptions;
+ }
- /// <inheritdoc />
- public event EventHandler<EventArgs>? Triggered;
+ /// <inheritdoc />
+ public event EventHandler<EventArgs>? Triggered;
- /// <inheritdoc />
- public TaskOptions TaskOptions { get; }
+ /// <inheritdoc />
+ public TaskOptions TaskOptions { get; }
- /// <inheritdoc />
- public async void Start(TaskResult? lastResult, ILogger logger, string taskName, bool isApplicationStartup)
+ /// <inheritdoc />
+ public async void Start(TaskResult? lastResult, ILogger logger, string taskName, bool isApplicationStartup)
+ {
+ if (isApplicationStartup)
{
- if (isApplicationStartup)
- {
- await Task.Delay(DelayMs).ConfigureAwait(false);
+ await Task.Delay(DelayMs).ConfigureAwait(false);
- OnTriggered();
- }
+ OnTriggered();
}
+ }
- /// <inheritdoc />
- public void Stop()
- {
- }
+ /// <inheritdoc />
+ public void Stop()
+ {
+ }
- /// <summary>
- /// Called when [triggered].
- /// </summary>
- private void OnTriggered()
- {
- Triggered?.Invoke(this, EventArgs.Empty);
- }
+ /// <summary>
+ /// Called when [triggered].
+ /// </summary>
+ private void OnTriggered()
+ {
+ Triggered?.Invoke(this, EventArgs.Empty);
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs
index ad94fdda5..79568f8a1 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs
@@ -3,108 +3,107 @@ using System.Threading;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
-namespace Emby.Server.Implementations.ScheduledTasks.Triggers
+namespace Emby.Server.Implementations.ScheduledTasks.Triggers;
+
+/// <summary>
+/// Represents a task trigger that fires on a weekly basis.
+/// </summary>
+public sealed class WeeklyTrigger : ITaskTrigger, IDisposable
{
+ private readonly TimeSpan _timeOfDay;
+ private readonly DayOfWeek _dayOfWeek;
+ private Timer? _timer;
+ private bool _disposed;
+
/// <summary>
- /// Represents a task trigger that fires on a weekly basis.
+ /// Initializes a new instance of the <see cref="WeeklyTrigger"/> class.
/// </summary>
- public sealed class WeeklyTrigger : ITaskTrigger, IDisposable
+ /// <param name="timeOfDay">The time of day to trigger the task to run.</param>
+ /// <param name="dayOfWeek">The day of week.</param>
+ /// <param name="taskOptions">The options of this task.</param>
+ public WeeklyTrigger(TimeSpan timeOfDay, DayOfWeek dayOfWeek, TaskOptions taskOptions)
{
- private readonly TimeSpan _timeOfDay;
- private readonly DayOfWeek _dayOfWeek;
- private Timer? _timer;
- private bool _disposed;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="WeeklyTrigger"/> class.
- /// </summary>
- /// <param name="timeofDay">The time of day to trigger the task to run.</param>
- /// <param name="dayOfWeek">The day of week.</param>
- /// <param name="taskOptions">The options of this task.</param>
- public WeeklyTrigger(TimeSpan timeofDay, DayOfWeek dayOfWeek, TaskOptions taskOptions)
- {
- _timeOfDay = timeofDay;
- _dayOfWeek = dayOfWeek;
- TaskOptions = taskOptions;
- }
+ _timeOfDay = timeOfDay;
+ _dayOfWeek = dayOfWeek;
+ TaskOptions = taskOptions;
+ }
- /// <inheritdoc />
- public event EventHandler<EventArgs>? Triggered;
+ /// <inheritdoc />
+ public event EventHandler<EventArgs>? Triggered;
- /// <inheritdoc />
- public TaskOptions TaskOptions { get; }
+ /// <inheritdoc />
+ public TaskOptions TaskOptions { get; }
- /// <inheritdoc />
- public void Start(TaskResult? lastResult, ILogger logger, string taskName, bool isApplicationStartup)
- {
- DisposeTimer();
+ /// <inheritdoc />
+ public void Start(TaskResult? lastResult, ILogger logger, string taskName, bool isApplicationStartup)
+ {
+ DisposeTimer();
- var triggerDate = GetNextTriggerDateTime();
+ var triggerDate = GetNextTriggerDateTime();
- _timer = new Timer(_ => OnTriggered(), null, triggerDate - DateTime.Now, TimeSpan.FromMilliseconds(-1));
- }
+ _timer = new Timer(_ => OnTriggered(), null, triggerDate - DateTime.Now, TimeSpan.FromMilliseconds(-1));
+ }
- /// <summary>
- /// Gets the next trigger date time.
- /// </summary>
- /// <returns>DateTime.</returns>
- private DateTime GetNextTriggerDateTime()
+ /// <summary>
+ /// Gets the next trigger date time.
+ /// </summary>
+ /// <returns>DateTime.</returns>
+ private DateTime GetNextTriggerDateTime()
+ {
+ var now = DateTime.Now;
+
+ // If it's on the same day
+ if (now.DayOfWeek == _dayOfWeek)
{
- var now = DateTime.Now;
+ // It's either later today, or a week from now
+ return now.TimeOfDay < _timeOfDay ? now.Date.Add(_timeOfDay) : now.Date.AddDays(7).Add(_timeOfDay);
+ }
- // If it's on the same day
- if (now.DayOfWeek == _dayOfWeek)
- {
- // It's either later today, or a week from now
- return now.TimeOfDay < _timeOfDay ? now.Date.Add(_timeOfDay) : now.Date.AddDays(7).Add(_timeOfDay);
- }
+ var triggerDate = now.Date;
- var triggerDate = now.Date;
+ // Walk the date forward until we get to the trigger day
+ while (triggerDate.DayOfWeek != _dayOfWeek)
+ {
+ triggerDate = triggerDate.AddDays(1);
+ }
- // Walk the date forward until we get to the trigger day
- while (triggerDate.DayOfWeek != _dayOfWeek)
- {
- triggerDate = triggerDate.AddDays(1);
- }
+ // Return the trigger date plus the time offset
+ return triggerDate.Add(_timeOfDay);
+ }
- // Return the trigger date plus the time offset
- return triggerDate.Add(_timeOfDay);
- }
+ /// <inheritdoc />
+ public void Stop()
+ {
+ DisposeTimer();
+ }
- /// <inheritdoc />
- public void Stop()
- {
- DisposeTimer();
- }
+ /// <summary>
+ /// Disposes the timer.
+ /// </summary>
+ private void DisposeTimer()
+ {
+ _timer?.Dispose();
+ _timer = null;
+ }
- /// <summary>
- /// Disposes the timer.
- /// </summary>
- private void DisposeTimer()
- {
- _timer?.Dispose();
- _timer = null;
- }
+ /// <summary>
+ /// Called when [triggered].
+ /// </summary>
+ private void OnTriggered()
+ {
+ Triggered?.Invoke(this, EventArgs.Empty);
+ }
- /// <summary>
- /// Called when [triggered].
- /// </summary>
- private void OnTriggered()
+ /// <inheritdoc />
+ public void Dispose()
+ {
+ if (_disposed)
{
- Triggered?.Invoke(this, EventArgs.Empty);
+ return;
}
- /// <inheritdoc />
- public void Dispose()
- {
- if (_disposed)
- {
- return;
- }
-
- DisposeTimer();
+ DisposeTimer();
- _disposed = true;
- }
+ _disposed = true;
}
}