fix(ha): read transcode store config from the variable form deployments set
The startup configuration only reads JELLYFIN_ prefixed environment variables, so the bare Jellyfin__TranscodeStore__* form used by the chart, the manifests and the README is dropped and the Redis store is never registered. Nothing logs the selected store, so the fallback is invisible. - Read bare Jellyfin__* variables into the Jellyfin:* configuration root - Keep an explicit JELLYFIN_ variable winning over the bare form - Log the selected transcode session store at startup - Ping Redis once at startup and log an unreachable store at Error - Log endpoints only, never the connection string
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Emby.Server.Implementations.MediaEncoding;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using StackExchange.Redis;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.Server.Tests.HighAvailability;
|
||||
|
||||
/// <summary>
|
||||
/// A Redis store that cannot be reached degrades silently: the client is configured not to abort the
|
||||
/// connection and every call site swallows failures. The probe is the only startup signal, so both of
|
||||
/// its outcomes are pinned here.
|
||||
/// </summary>
|
||||
public sealed class TranscodeStoreConnectivityProbeTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task StartAsync_Should_Log_Information_When_Reachable()
|
||||
{
|
||||
var database = new Mock<IDatabase>();
|
||||
database.Setup(db => db.PingAsync(It.IsAny<CommandFlags>())).ReturnsAsync(TimeSpan.FromMilliseconds(3));
|
||||
|
||||
var (logger, probe) = CreateProbe(database.Object);
|
||||
|
||||
await probe.StartAsync(CancellationToken.None);
|
||||
|
||||
Assert.True(logger.HasEntry(LogLevel.Information, "reachable"));
|
||||
Assert.DoesNotContain(logger.Entries, entry => entry.Level >= LogLevel.Warning);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartAsync_Should_Log_Error_When_Unreachable()
|
||||
{
|
||||
var database = new Mock<IDatabase>();
|
||||
database.Setup(db => db.PingAsync(It.IsAny<CommandFlags>()))
|
||||
.ThrowsAsync(new RedisConnectionException(ConnectionFailureType.UnableToConnect, "no route to host"));
|
||||
|
||||
var (logger, probe) = CreateProbe(database.Object);
|
||||
|
||||
await probe.StartAsync(CancellationToken.None);
|
||||
|
||||
Assert.True(logger.HasEntry(LogLevel.Error, "UNREACHABLE"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartAsync_Should_Log_Error_Instead_Of_Aborting_Startup()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IConnectionMultiplexer>(_ => throw new RedisConnectionException(ConnectionFailureType.UnableToConnect, "no route to host"));
|
||||
using var provider = services.BuildServiceProvider();
|
||||
|
||||
var logger = new RecordingLogger<TranscodeStoreConnectivityProbe>();
|
||||
var probe = new TranscodeStoreConnectivityProbe(provider, logger);
|
||||
|
||||
await probe.StartAsync(CancellationToken.None);
|
||||
|
||||
Assert.True(logger.HasEntry(LogLevel.Error, "UNREACHABLE"));
|
||||
}
|
||||
|
||||
private static (RecordingLogger<TranscodeStoreConnectivityProbe> Logger, TranscodeStoreConnectivityProbe Probe) CreateProbe(IDatabase database)
|
||||
{
|
||||
var multiplexer = new Mock<IConnectionMultiplexer>();
|
||||
multiplexer.Setup(redis => redis.GetDatabase(It.IsAny<int>(), It.IsAny<object>())).Returns(database);
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton(multiplexer.Object);
|
||||
var provider = services.BuildServiceProvider();
|
||||
|
||||
var logger = new RecordingLogger<TranscodeStoreConnectivityProbe>();
|
||||
return (logger, new TranscodeStoreConnectivityProbe(provider, logger));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user