< Summary - Jellyfin

Information
Class: Emby.Server.Implementations.ScheduledTasks.TaskManager
Assembly: Emby.Server.Implementations
File(s): /srv/git/jellyfin/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs
Line coverage
70%
Covered lines: 55
Uncovered lines: 23
Coverable lines: 78
Total lines: 263
Line coverage: 70.5%
Branch coverage
61%
Covered branches: 22
Total branches: 36
Branch coverage: 61.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
CancelIfRunningAndQueue(...)100%22100%
CancelIfRunningAndQueue()100%11100%
CancelIfRunning()0%620%
QueueScheduledTask(...)75%4480%
QueueScheduledTask()100%210%
QueueIfNotRunning()0%2040%
Execute()0%4260%
QueueScheduledTask(...)50%2280%
QueueScheduledTask(...)100%22100%
AddTasks(...)100%11100%
Dispose()100%11100%
Dispose(...)100%22100%
Cancel(...)100%210%
Execute(...)100%11100%
OnTaskExecuting(...)100%22100%
OnTaskCompleted(...)100%22100%
ExecuteQueuedTasks()100%88100%

File(s)

/srv/git/jellyfin/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs

#LineLine coverage
 1using System;
 2using System.Collections.Concurrent;
 3using System.Collections.Generic;
 4using System.Linq;
 5using System.Threading.Tasks;
 6using Jellyfin.Data.Events;
 7using MediaBrowser.Common.Configuration;
 8using MediaBrowser.Model.Tasks;
 9using Microsoft.Extensions.Logging;
 10
 11namespace Emby.Server.Implementations.ScheduledTasks;
 12
 13/// <summary>
 14/// Class TaskManager.
 15/// </summary>
 16public class TaskManager : ITaskManager
 17{
 18    /// <summary>
 19    /// The _task queue.
 20    /// </summary>
 2121    private readonly ConcurrentQueue<Tuple<Type, TaskOptions>> _taskQueue =
 2122        new ConcurrentQueue<Tuple<Type, TaskOptions>>();
 23
 24    private readonly IApplicationPaths _applicationPaths;
 25    private readonly ILogger<TaskManager> _logger;
 26
 27    /// <summary>
 28    /// Initializes a new instance of the <see cref="TaskManager" /> class.
 29    /// </summary>
 30    /// <param name="applicationPaths">The application paths.</param>
 31    /// <param name="logger">The logger.</param>
 32    public TaskManager(
 33        IApplicationPaths applicationPaths,
 34        ILogger<TaskManager> logger)
 35    {
 2136        _applicationPaths = applicationPaths;
 2137        _logger = logger;
 38
 2139        ScheduledTasks = [];
 2140    }
 41
 42    /// <inheritdoc />
 43    public event EventHandler<GenericEventArgs<IScheduledTaskWorker>>? TaskExecuting;
 44
 45    /// <inheritdoc />
 46    public event EventHandler<TaskCompletionEventArgs>? TaskCompleted;
 47
 48    /// <inheritdoc />
 49    public IReadOnlyList<IScheduledTaskWorker> ScheduledTasks { get; private set; }
 50
 51    /// <inheritdoc />
 52    public void CancelIfRunningAndQueue<T>(TaskOptions options)
 53        where T : IScheduledTask
 54    {
 2055        var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
 2056        ((ScheduledTaskWorker)task).CancelIfRunning();
 57
 2058        QueueScheduledTask<T>(options);
 2059    }
 60
 61    /// <inheritdoc />
 62    public void CancelIfRunningAndQueue<T>()
 63            where T : IScheduledTask
 64    {
 2065        CancelIfRunningAndQueue<T>(new TaskOptions());
 2066    }
 67
 68    /// <inheritdoc />
 69    public void CancelIfRunning<T>()
 70                where T : IScheduledTask
 71    {
 072        var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
 073        ((ScheduledTaskWorker)task).CancelIfRunning();
 074    }
 75
 76    /// <inheritdoc />
 77    public void QueueScheduledTask<T>(TaskOptions options)
 78        where T : IScheduledTask
 79    {
 2080        var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == typeof(T));
 81
 2082        if (scheduledTask is null)
 83        {
 084            _logger.LogError("Unable to find scheduled task of type {Type} in QueueScheduledTask.", typeof(T).Name);
 85        }
 86        else
 87        {
 2088            QueueScheduledTask(scheduledTask, options);
 89        }
 2090    }
 91
 92    /// <inheritdoc />
 93    public void QueueScheduledTask<T>()
 94        where T : IScheduledTask
 95    {
 096        QueueScheduledTask<T>(new TaskOptions());
 097    }
 98
 99    /// <inheritdoc />
 100    public void QueueIfNotRunning<T>()
 101        where T : IScheduledTask
 102    {
 0103        var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
 104
 0105        if (task.State != TaskState.Running)
 106        {
 0107            QueueScheduledTask<T>(new TaskOptions());
 108        }
 0109    }
 110
 111    /// <inheritdoc />
 112    public void Execute<T>()
 113        where T : IScheduledTask
 114    {
 0115        var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == typeof(T));
 116
 0117        if (scheduledTask is null)
 118        {
 0119            _logger.LogError("Unable to find scheduled task of type {Type} in Execute.", typeof(T).Name);
 120        }
 121        else
 122        {
 0123            var type = scheduledTask.ScheduledTask.GetType();
 124
 0125            _logger.LogDebug("Queuing task {Name}", type.Name);
 126
 0127            lock (_taskQueue)
 128            {
 0129                if (scheduledTask.State == TaskState.Idle)
 130                {
 0131                    Execute(scheduledTask, new TaskOptions());
 132                }
 0133            }
 134        }
 0135    }
 136
 137    /// <inheritdoc />
 138    public void QueueScheduledTask(IScheduledTask task, TaskOptions options)
 139    {
 6140        var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == task.GetType());
 141
 6142        if (scheduledTask is null)
 143        {
 0144            _logger.LogError("Unable to find scheduled task of type {Type} in QueueScheduledTask.", task.GetType().Name)
 145        }
 146        else
 147        {
 6148            QueueScheduledTask(scheduledTask, options);
 149        }
 6150    }
 151
 152    /// <summary>
 153    /// Queues the scheduled task.
 154    /// </summary>
 155    /// <param name="task">The task.</param>
 156    /// <param name="options">The task options.</param>
 157    private void QueueScheduledTask(IScheduledTaskWorker task, TaskOptions options)
 158    {
 26159        var type = task.ScheduledTask.GetType();
 160
 26161        _logger.LogDebug("Queuing task {Name}", type.Name);
 162
 26163        lock (_taskQueue)
 164        {
 26165            if (task.State == TaskState.Idle)
 166            {
 24167                Execute(task, options);
 24168                return;
 169            }
 170
 2171            _taskQueue.Enqueue(new Tuple<Type, TaskOptions>(type, options));
 2172        }
 26173    }
 174
 175    /// <inheritdoc />
 176    public void AddTasks(IEnumerable<IScheduledTask> tasks)
 177    {
 21178        var list = tasks.Select(t => new ScheduledTaskWorker(t, _applicationPaths, this, _logger));
 179
 21180        ScheduledTasks = ScheduledTasks.Concat(list).ToArray();
 21181    }
 182
 183    /// <inheritdoc />
 184    public void Dispose()
 185    {
 21186        Dispose(true);
 21187        GC.SuppressFinalize(this);
 21188    }
 189
 190    /// <summary>
 191    /// Releases unmanaged and - optionally - managed resources.
 192    /// </summary>
 193    /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only 
 194    protected virtual void Dispose(bool dispose)
 195    {
 840196        foreach (var task in ScheduledTasks)
 197        {
 399198            task.Dispose();
 199        }
 21200    }
 201
 202    /// <inheritdoc />
 203    public void Cancel(IScheduledTaskWorker task)
 204    {
 0205        ((ScheduledTaskWorker)task).Cancel();
 0206    }
 207
 208    /// <inheritdoc />
 209    public Task Execute(IScheduledTaskWorker task, TaskOptions options)
 210    {
 25211        return ((ScheduledTaskWorker)task).Execute(options);
 212    }
 213
 214    /// <summary>
 215    /// Called when [task executing].
 216    /// </summary>
 217    /// <param name="task">The task.</param>
 218    internal void OnTaskExecuting(IScheduledTaskWorker task)
 219    {
 25220        TaskExecuting?.Invoke(this, new GenericEventArgs<IScheduledTaskWorker>(task));
 22221    }
 222
 223    /// <summary>
 224    /// Called when [task completed].
 225    /// </summary>
 226    /// <param name="task">The task.</param>
 227    /// <param name="result">The result.</param>
 228    internal void OnTaskCompleted(IScheduledTaskWorker task, TaskResult result)
 229    {
 33230        TaskCompleted?.Invoke(task, new TaskCompletionEventArgs(task, result));
 231
 33232        ExecuteQueuedTasks();
 33233    }
 234
 235    /// <summary>
 236    /// Executes the queued tasks.
 237    /// </summary>
 238    private void ExecuteQueuedTasks()
 239    {
 33240        lock (_taskQueue)
 241        {
 33242            var list = new List<Tuple<Type, TaskOptions>>();
 243
 35244            while (_taskQueue.TryDequeue(out var item))
 245            {
 2246                if (list.All(i => i.Item1 != item.Item1))
 247                {
 2248                    list.Add(item);
 249                }
 2250            }
 251
 70252            foreach (var enqueuedType in list)
 253            {
 2254                var scheduledTask = ScheduledTasks.First(t => t.ScheduledTask.GetType() == enqueuedType.Item1);
 255
 2256                if (scheduledTask.State == TaskState.Idle)
 257                {
 1258                    Execute(scheduledTask, enqueuedType.Item2);
 259                }
 260            }
 261        }
 33262    }
 263}