Complete multi-instance support: Phases 3–6 & deployment
- Implements Phases 3–6: session isolation, cache coordination, primary election, and file system monitor coordination for Jellyfin with PostgreSQL. - Adds new database entities (Instance, DistributedLock, FileSystemChange) and EF model configurations. - Includes SQL migration scripts and EF migration for all required tables, columns, and helper functions. - Updates Device entity and JellyfinDbContext for multi-instance tracking. - Integrates new DI services for instance registry, distributed locks, cache coordinator, and primary election. - Adds publishing profiles (Win/Linux/FrameworkDependent) and automation script for deployment. - Extensive documentation for architecture, setup, and publishing. - All changes are backward compatible and build successfully.
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
// <copyright file="PrimaryInstanceTaskManager.cs" company="PlaceholderCompany">
|
||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Task manager decorator that ensures scheduled tasks only run on the primary instance.
|
||||
/// </summary>
|
||||
public sealed class PrimaryInstanceTaskManager : ITaskManager
|
||||
{
|
||||
private readonly ITaskManager _innerTaskManager;
|
||||
private readonly IPrimaryElectionService _primaryElectionService;
|
||||
private readonly ILogger<PrimaryInstanceTaskManager> _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PrimaryInstanceTaskManager"/> class.
|
||||
/// </summary>
|
||||
/// <param name="innerTaskManager">The inner task manager.</param>
|
||||
/// <param name="primaryElectionService">The primary election service.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public PrimaryInstanceTaskManager(
|
||||
ITaskManager innerTaskManager,
|
||||
IPrimaryElectionService primaryElectionService,
|
||||
ILogger<PrimaryInstanceTaskManager> logger)
|
||||
{
|
||||
_innerTaskManager = innerTaskManager;
|
||||
_primaryElectionService = primaryElectionService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<GenericEventArgs<IScheduledTaskWorker>>? TaskExecuting
|
||||
{
|
||||
add => _innerTaskManager.TaskExecuting += value;
|
||||
remove => _innerTaskManager.TaskExecuting -= value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<TaskCompletionEventArgs>? TaskCompleted
|
||||
{
|
||||
add => _innerTaskManager.TaskCompleted += value;
|
||||
remove => _innerTaskManager.TaskCompleted -= value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IReadOnlyList<IScheduledTaskWorker> ScheduledTasks => _innerTaskManager.ScheduledTasks;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void CancelIfRunningAndQueue<T>(TaskOptions options)
|
||||
where T : IScheduledTask
|
||||
{
|
||||
if (ShouldExecuteTask<T>())
|
||||
{
|
||||
_innerTaskManager.CancelIfRunningAndQueue<T>(options);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void CancelIfRunningAndQueue<T>()
|
||||
where T : IScheduledTask
|
||||
{
|
||||
if (ShouldExecuteTask<T>())
|
||||
{
|
||||
_innerTaskManager.CancelIfRunningAndQueue<T>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void CancelIfRunning<T>()
|
||||
where T : IScheduledTask
|
||||
{
|
||||
_innerTaskManager.CancelIfRunning<T>();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void QueueScheduledTask<T>(TaskOptions options)
|
||||
where T : IScheduledTask
|
||||
{
|
||||
if (ShouldExecuteTask<T>())
|
||||
{
|
||||
_innerTaskManager.QueueScheduledTask<T>(options);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void QueueScheduledTask<T>()
|
||||
where T : IScheduledTask
|
||||
{
|
||||
if (ShouldExecuteTask<T>())
|
||||
{
|
||||
_innerTaskManager.QueueScheduledTask<T>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void QueueIfNotRunning<T>()
|
||||
where T : IScheduledTask
|
||||
{
|
||||
if (ShouldExecuteTask<T>())
|
||||
{
|
||||
_innerTaskManager.QueueIfNotRunning<T>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Execute<T>()
|
||||
where T : IScheduledTask
|
||||
{
|
||||
if (ShouldExecuteTask<T>())
|
||||
{
|
||||
_innerTaskManager.Execute<T>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void QueueScheduledTask(IScheduledTask task, TaskOptions options)
|
||||
{
|
||||
if (ShouldExecuteTask(task.GetType()))
|
||||
{
|
||||
_innerTaskManager.QueueScheduledTask(task, options);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void AddTasks(IEnumerable<IScheduledTask> tasks)
|
||||
{
|
||||
_innerTaskManager.AddTasks(tasks);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Cancel(IScheduledTaskWorker task)
|
||||
{
|
||||
_innerTaskManager.Cancel(task);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task Execute(IScheduledTaskWorker task, TaskOptions options)
|
||||
{
|
||||
if (ShouldExecuteTask(task.ScheduledTask.GetType()))
|
||||
{
|
||||
return _innerTaskManager.Execute(task, options);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
_innerTaskManager.Dispose();
|
||||
}
|
||||
|
||||
private bool ShouldExecuteTask<T>()
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user