< 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
60%
Covered lines: 47
Uncovered lines: 31
Coverable lines: 78
Total lines: 264
Line coverage: 60.2%
Branch coverage
47%
Covered branches: 17
Total branches: 36
Branch coverage: 47.2%
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%4.13480%
QueueScheduledTask()100%210%
QueueIfNotRunning()0%2040%
Execute()0%4260%
QueueScheduledTask(...)50%2.03280%
QueueScheduledTask(...)50%2.04277.77%
AddTasks(...)100%11100%
Dispose()100%11100%
Dispose(...)100%22100%
Cancel(...)100%210%
Execute(...)100%11100%
OnTaskExecuting(...)100%22100%
OnTaskCompleted(...)100%22100%
ExecuteQueuedTasks()50%18.39845.45%

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>
 16    public class TaskManager : ITaskManager
 17    {
 18        /// <summary>
 19        /// The _task queue.
 20        /// </summary>
 2221        private readonly ConcurrentQueue<Tuple<Type, TaskOptions>> _taskQueue =
 2222            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        {
 2236            _applicationPaths = applicationPaths;
 2237            _logger = logger;
 38
 2239            ScheduledTasks = Array.Empty<IScheduledTaskWorker>();
 2240        }
 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 {0} 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 {0} in Execute.", typeof(T).Name);
 120            }
 121            else
 122            {
 0123                var type = scheduledTask.ScheduledTask.GetType();
 124
 0125                _logger.LogDebug("Queuing task {0}", 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        {
 3140            var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == task.GetType());
 141
 3142            if (scheduledTask is null)
 143            {
 0144                _logger.LogError("Unable to find scheduled task of type {0} in QueueScheduledTask.", task.GetType().Name
 145            }
 146            else
 147            {
 3148                QueueScheduledTask(scheduledTask, options);
 149            }
 3150        }
 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        {
 23159            var type = task.ScheduledTask.GetType();
 160
 23161            _logger.LogDebug("Queuing task {0}", type.Name);
 162
 23163            lock (_taskQueue)
 164            {
 23165                if (task.State == TaskState.Idle)
 166                {
 23167                    Execute(task, options);
 23168                    return;
 169                }
 170
 0171                _taskQueue.Enqueue(new Tuple<Type, TaskOptions>(type, options));
 0172            }
 23173        }
 174
 175        /// <inheritdoc />
 176        public void AddTasks(IEnumerable<IScheduledTask> tasks)
 177        {
 22178            var list = tasks.Select(t => new ScheduledTaskWorker(t, _applicationPaths, this, _logger));
 179
 22180            ScheduledTasks = ScheduledTasks.Concat(list).ToArray();
 22181        }
 182
 183        /// <inheritdoc />
 184        public void Dispose()
 185        {
 22186            Dispose(true);
 22187            GC.SuppressFinalize(this);
 22188        }
 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 o
 194        protected virtual void Dispose(bool dispose)
 195        {
 880196            foreach (var task in ScheduledTasks)
 197            {
 418198                task.Dispose();
 199            }
 22200        }
 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        {
 23211            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        {
 23220            TaskExecuting?.Invoke(this, new GenericEventArgs<IScheduledTaskWorker>(task));
 20221        }
 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        {
 24230            TaskCompleted?.Invoke(task, new TaskCompletionEventArgs(task, result));
 231
 24232            ExecuteQueuedTasks();
 24233        }
 234
 235        /// <summary>
 236        /// Executes the queued tasks.
 237        /// </summary>
 238        private void ExecuteQueuedTasks()
 239        {
 24240            lock (_taskQueue)
 241            {
 24242                var list = new List<Tuple<Type, TaskOptions>>();
 243
 24244                while (_taskQueue.TryDequeue(out var item))
 245                {
 0246                    if (list.All(i => i.Item1 != item.Item1))
 247                    {
 0248                        list.Add(item);
 249                    }
 0250                }
 251
 48252                foreach (var enqueuedType in list)
 253                {
 0254                    var scheduledTask = ScheduledTasks.First(t => t.ScheduledTask.GetType() == enqueuedType.Item1);
 255
 0256                    if (scheduledTask.State == TaskState.Idle)
 257                    {
 0258                        Execute(scheduledTask, enqueuedType.Item2);
 259                    }
 260                }
 261            }
 24262        }
 263    }
 264}