using System;
using System.Collections.Generic;
using System.Linq;
using MediaBrowser.Common.Configuration;
namespace Jellyfin.Server.Implementations.Tests.Configuration;
///
/// An in-process stand-in for the Redis pub/sub bus: every endpoint connected to one fabric receives
/// what the others publish, and never its own notices.
///
internal sealed class FakeInvalidationBusFabric
{
private readonly List _endpoints = new();
///
/// Connects a new instance to the fabric.
///
/// The identity of the connecting instance.
/// The bus of that instance.
public IConfigurationInvalidationBus Connect(string originId)
{
var endpoint = new Endpoint(this, originId);
lock (_endpoints)
{
_endpoints.Add(endpoint);
}
return endpoint;
}
private void Broadcast(ConfigurationInvalidation invalidation)
{
Endpoint[] endpoints;
lock (_endpoints)
{
endpoints = _endpoints.ToArray();
}
foreach (var endpoint in endpoints.Where(e => !string.Equals(e.OriginId, invalidation.OriginId, StringComparison.Ordinal)))
{
endpoint.Deliver(invalidation);
}
}
private sealed class Endpoint : IConfigurationInvalidationBus
{
private readonly FakeInvalidationBusFabric _fabric;
private readonly List> _handlers = new();
public Endpoint(FakeInvalidationBusFabric fabric, string originId)
{
_fabric = fabric;
OriginId = originId;
}
public string OriginId { get; }
public void Publish(ConfigurationInvalidationScope scope, string? target)
=> _fabric.Broadcast(new ConfigurationInvalidation { Scope = scope, Target = target, OriginId = OriginId });
public void Subscribe(Action handler)
=> _handlers.Add(handler);
public void Deliver(ConfigurationInvalidation invalidation)
{
foreach (var handler in _handlers)
{
handler(invalidation);
}
}
}
}