using System;
using System.Linq;
using Emby.Server.Implementations.MediaEncoding;
using MediaBrowser.Controller.MediaEncoding;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;
namespace Jellyfin.Server.Extensions;
///
/// Extensions for registering the transcode session store.
///
public static class TranscodeStoreServiceCollectionExtensions
{
///
/// Registers the transcode session store, Redis-backed when a connection string is configured and
/// no-op otherwise, and reports the selected store at .
///
/// The service collection.
/// The configuration to read Jellyfin:TranscodeStore from.
/// The logger to report the selected store on.
/// The updated service collection.
public static IServiceCollection AddTranscodeSessionStore(
this IServiceCollection serviceCollection,
IConfiguration configuration,
ILogger logger)
{
ArgumentNullException.ThrowIfNull(configuration);
ArgumentNullException.ThrowIfNull(logger);
serviceCollection.Configure(configuration.GetSection(TranscodeStoreOptions.ConfigurationSection));
var redisConnectionString = configuration[TranscodeStoreOptions.RedisConnectionStringKey];
if (string.IsNullOrEmpty(redisConnectionString))
{
logger.LogInformation(
"Transcode session store: {Store}. Cross-pod transcode takeover is off; set {Key} to enable it.",
nameof(NullTranscodeSessionStore),
TranscodeStoreOptions.RedisConnectionStringKey);
return serviceCollection.AddSingleton();
}
logger.LogInformation(
"Transcode session store: {Store} on {Endpoints}.",
nameof(RedisTranscodeSessionStore),
DescribeEndpoints(redisConnectionString));
serviceCollection.AddSingleton(sp =>
{
try
{
return ConnectionMultiplexer.Connect(redisConnectionString);
}
catch (Exception ex)
{
sp.GetRequiredService>()
.LogError(ex, "Failed to connect to Redis. Check the {Key} configuration.", TranscodeStoreOptions.RedisConnectionStringKey);
throw;
}
});
serviceCollection.AddSingleton();
serviceCollection.AddHostedService();
return serviceCollection;
}
///
/// Renders the endpoints of a connection string for logging. The connection string itself is never
/// logged because it can carry a password.
///
private static string DescribeEndpoints(string redisConnectionString)
{
try
{
return string.Join(
',',
ConfigurationOptions.Parse(redisConnectionString).EndPoints.Select(endpoint => endpoint.ToString()));
}
catch (ArgumentException)
{
return "(unparsable connection string)";
}
}
}