//
// 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;
}
}
}