using System;
using Emby.Server.Implementations.ScheduledTasks;
using MediaBrowser.Controller.ScheduledTasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Server.Extensions;
///
/// Extensions for registering the scan-leader lease.
///
public static class ScanLeaderServiceCollectionExtensions
{
private const string RedisConnectionStringKey = "Jellyfin:TranscodeStore:RedisConnectionString";
///
/// Registers the scan-leader lease and reports at whether
/// timer-driven library tasks are gated to a single instance.
///
///
/// Gating is on by default once a Redis connection string is configured: that is only set for a
/// multi-instance deployment, which is the only shape where running library scans on every
/// instance is wrong. Single-instance installs have no Redis and keep running every task locally.
///
/// The service collection.
/// The configuration to read Jellyfin:ScanLeader from.
/// The logger to report the gating decision on.
/// The updated service collection.
public static IServiceCollection AddScanLeaderLease(
this IServiceCollection serviceCollection,
IConfiguration configuration,
ILogger logger)
{
ArgumentNullException.ThrowIfNull(configuration);
ArgumentNullException.ThrowIfNull(logger);
serviceCollection.Configure(configuration.GetSection(ScanLeaderOptions.ConfigurationSection));
var redisConfigured = !string.IsNullOrEmpty(configuration[RedisConnectionStringKey]);
var requested = bool.TryParse(configuration[ScanLeaderOptions.EnabledKey], out var explicitChoice)
? explicitChoice
: redisConfigured;
var active = requested && redisConfigured;
// The task worker reads Enabled from the bound options, so the effective decision has to land
// there as well as on the lease registration below.
serviceCollection.PostConfigure(options => options.Enabled = active);
if (active)
{
logger.LogInformation(
"Scan-leader gating is active: timer-driven library tasks run only on the instance holding the Redis scan-leader lease.");
return serviceCollection.AddSingleton();
}
if (requested)
{
logger.LogWarning(
"Scan-leader gating is enabled but no Redis connection string is configured ({Key}), so it cannot run: timer-driven library tasks run on every instance.",
RedisConnectionStringKey);
}
else
{
logger.LogInformation("Scan-leader gating is off: timer-driven library tasks run on every instance.");
}
return serviceCollection.AddSingleton();
}
}