// // Copyright (c) PlaceholderCompany. All rights reserved. // namespace Jellyfin.Server.Implementations.Clustering { using System; using System.Collections.Generic; using System.Threading.Tasks; using Jellyfin.Data.Events; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; /// /// Task manager decorator that ensures scheduled tasks only run on the primary instance. /// public sealed class PrimaryInstanceTaskManager : ITaskManager { private readonly ITaskManager _innerTaskManager; private readonly IPrimaryElectionService _primaryElectionService; private readonly ILogger _logger; /// /// Initializes a new instance of the class. /// /// The inner task manager. /// The primary election service. /// The logger. public PrimaryInstanceTaskManager( ITaskManager innerTaskManager, IPrimaryElectionService primaryElectionService, ILogger logger) { _innerTaskManager = innerTaskManager; _primaryElectionService = primaryElectionService; _logger = logger; } /// public event EventHandler>? TaskExecuting { add => _innerTaskManager.TaskExecuting += value; remove => _innerTaskManager.TaskExecuting -= value; } /// public event EventHandler? TaskCompleted { add => _innerTaskManager.TaskCompleted += value; remove => _innerTaskManager.TaskCompleted -= value; } /// public IReadOnlyList ScheduledTasks => _innerTaskManager.ScheduledTasks; /// public void CancelIfRunningAndQueue(TaskOptions options) where T : IScheduledTask { if (ShouldExecuteTask()) { _innerTaskManager.CancelIfRunningAndQueue(options); } } /// public void CancelIfRunningAndQueue() where T : IScheduledTask { if (ShouldExecuteTask()) { _innerTaskManager.CancelIfRunningAndQueue(); } } /// public void CancelIfRunning() where T : IScheduledTask { _innerTaskManager.CancelIfRunning(); } /// public void QueueScheduledTask(TaskOptions options) where T : IScheduledTask { if (ShouldExecuteTask()) { _innerTaskManager.QueueScheduledTask(options); } } /// public void QueueScheduledTask() where T : IScheduledTask { if (ShouldExecuteTask()) { _innerTaskManager.QueueScheduledTask(); } } /// public void QueueIfNotRunning() where T : IScheduledTask { if (ShouldExecuteTask()) { _innerTaskManager.QueueIfNotRunning(); } } /// public void Execute() where T : IScheduledTask { if (ShouldExecuteTask()) { _innerTaskManager.Execute(); } } /// public void QueueScheduledTask(IScheduledTask task, TaskOptions options) { if (ShouldExecuteTask(task.GetType())) { _innerTaskManager.QueueScheduledTask(task, options); } } /// public void AddTasks(IEnumerable tasks) { _innerTaskManager.AddTasks(tasks); } /// public void Cancel(IScheduledTaskWorker task) { _innerTaskManager.Cancel(task); } /// public Task Execute(IScheduledTaskWorker task, TaskOptions options) { if (ShouldExecuteTask(task.ScheduledTask.GetType())) { return _innerTaskManager.Execute(task, options); } return Task.CompletedTask; } /// public void Dispose() { _innerTaskManager.Dispose(); } private bool ShouldExecuteTask() where T : IScheduledTask { return ShouldExecuteTask(typeof(T)); } private bool ShouldExecuteTask(Type taskType) { if (!_primaryElectionService.ShouldExecuteScheduledTasks()) { _logger.LogDebug( "Skipping task {TaskName} - not primary instance. Primary: {PrimaryId}", taskType.Name, _primaryElectionService.PrimaryInstanceId); return false; } return true; } } }