using Microsoft.Extensions.DependencyInjection;
using StellaOps.Plugin.Abstractions;
using StellaOps.Plugin.Abstractions.Capabilities;
using StellaOps.Router.Common.Plugins;
namespace StellaOps.Router.Plugin.Unified;
///
/// Factory for creating unified transport plugin adapters from existing router transport plugins.
///
public sealed class TransportPluginAdapterFactory
{
private readonly IEnumerable _plugins;
private readonly Dictionary _adapters = new(StringComparer.OrdinalIgnoreCase);
private readonly object _lock = new();
///
/// Known transport protocols for each transport type.
///
private static readonly Dictionary KnownProtocols = new(StringComparer.OrdinalIgnoreCase)
{
["tcp"] = TransportProtocol.Tcp,
["tls"] = TransportProtocol.Tls,
["udp"] = TransportProtocol.Udp,
["rabbitmq"] = TransportProtocol.Amqp,
["valkey"] = TransportProtocol.Redis,
["redis"] = TransportProtocol.Redis,
["inmemory"] = TransportProtocol.InMemory
};
///
/// Known features for each transport type.
///
private static readonly Dictionary KnownFeatures = new(StringComparer.OrdinalIgnoreCase)
{
["tcp"] = TransportFeatures.RequestReply | TransportFeatures.Streaming | TransportFeatures.ConnectionPooling,
["tls"] = TransportFeatures.RequestReply | TransportFeatures.Streaming | TransportFeatures.TlsSupport | TransportFeatures.ConnectionPooling,
["udp"] = TransportFeatures.None, // UDP is connectionless, fire-and-forget
["rabbitmq"] = TransportFeatures.RequestReply | TransportFeatures.PubSub | TransportFeatures.Queuing | TransportFeatures.Acknowledgment | TransportFeatures.AutoReconnect,
["valkey"] = TransportFeatures.PubSub | TransportFeatures.Queuing | TransportFeatures.AutoReconnect,
["redis"] = TransportFeatures.PubSub | TransportFeatures.Queuing | TransportFeatures.AutoReconnect,
["inmemory"] = TransportFeatures.RequestReply | TransportFeatures.Streaming
};
///
/// Creates a new factory instance.
///
/// The available router transport plugins.
public TransportPluginAdapterFactory(IEnumerable plugins)
{
_plugins = plugins ?? throw new ArgumentNullException(nameof(plugins));
}
///
/// Gets all available unified transport plugins.
///
/// Service provider for availability checking.
/// List of unified transport plugins.
public IReadOnlyList GetAllPlugins(IServiceProvider serviceProvider)
{
var result = new List();
foreach (var plugin in _plugins)
{
if (plugin.IsAvailable(serviceProvider))
{
var adapter = GetOrCreateAdapter(plugin);
if (adapter != null)
{
result.Add(adapter);
}
}
}
return result;
}
///
/// Gets a unified transport plugin by transport name.
///
/// Transport name (e.g., "tcp", "tls", "rabbitmq").
/// Unified transport plugin, or null if not found.
public IPlugin? GetPlugin(string transportName)
{
var plugin = _plugins.FirstOrDefault(p =>
p.TransportName.Equals(transportName, StringComparison.OrdinalIgnoreCase));
if (plugin == null)
{
return null;
}
return GetOrCreateAdapter(plugin);
}
///
/// Gets the transport capability for a transport.
///
/// Transport name.
/// Transport capability, or null if not found.
public ITransportCapability? GetCapability(string transportName)
{
return GetPlugin(transportName) as ITransportCapability;
}
///
/// Gets all available transport names.
///
/// List of transport names.
public IReadOnlyList GetAvailableTransports()
{
return _plugins.Select(p => p.TransportName).ToList();
}
private TransportPluginAdapter? GetOrCreateAdapter(IRouterTransportPlugin plugin)
{
lock (_lock)
{
if (_adapters.TryGetValue(plugin.TransportName, out var existing))
{
return existing;
}
var protocol = KnownProtocols.TryGetValue(plugin.TransportName, out var p)
? p
: TransportProtocol.Tcp; // Default to TCP
var features = KnownFeatures.TryGetValue(plugin.TransportName, out var f)
? f
: TransportFeatures.RequestReply; // Default to request/reply
var adapter = new TransportPluginAdapter(plugin, protocol, features);
_adapters[plugin.TransportName] = adapter;
return adapter;
}
}
}
///
/// Extension methods for registering unified transport plugin services.
///
public static class TransportPluginAdapterExtensions
{
///
/// Adds unified transport plugin adapter services to the service collection.
///
/// Service collection.
/// Service collection for chaining.
public static IServiceCollection AddUnifiedTransportPlugins(this IServiceCollection services)
{
services.AddSingleton();
return services;
}
}