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; } }