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;
///
/// A transcode store that cannot be reached degrades silently: the client is configured not to abort
/// the connection and every call site swallows failures. Quick connect's startup read is what stops a
/// pod coming up against a dead store; this probe only reports it, so both of its outcomes are pinned
/// here - including that it never throws, which is what keeps the two policies from competing.
///
public sealed class TranscodeStoreConnectivityProbeTests
{
[Fact]
public async Task StartAsync_Should_Log_Information_When_Reachable()
{
var database = new Mock();
database.Setup(db => db.PingAsync(It.IsAny())).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();
database.Setup(db => db.PingAsync(It.IsAny()))
.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(_ => throw new RedisConnectionException(ConnectionFailureType.UnableToConnect, "no route to host"));
using var provider = services.BuildServiceProvider();
var logger = new RecordingLogger();
var probe = new TranscodeStoreConnectivityProbe(provider, logger);
await probe.StartAsync(CancellationToken.None);
Assert.True(logger.HasEntry(LogLevel.Error, "UNREACHABLE"));
}
private static (RecordingLogger Logger, TranscodeStoreConnectivityProbe Probe) CreateProbe(IDatabase database)
{
var multiplexer = new Mock();
multiplexer.Setup(redis => redis.GetDatabase(It.IsAny(), It.IsAny