public void Subscribe(IProxy proxy, EventInfo @event, Delegate @delegate) { var eventDesc = new EventDescriptor { ServiceId = ((ServiceProxyContext)proxy.Context).Service.Id, EventId = _eventIdProvider.GetId(@event) }; if (@delegate.Target is IProxy subscriberProxy) { var subscriberProxyContext = (ServiceProxyContext)(subscriberProxy.Context ?? ServiceProxyBuildingContext.CurrentServiceProxyContext); var subscriberServiceId = subscriberProxyContext.Service.Id; var subscriberMethodId = _routineMethodIdProvider.GetId(@delegate.GetMethodInfo()); var subscriberDesc = new EventSubscriberDescriptor { ServiceId = subscriberServiceId, MethodId = subscriberMethodId }; _eventSubscriber.Subscribe(eventDesc, subscriberDesc); } else { throw new NotSupportedException("At this moment event subscribers must be routines of services."); } }
public Task <IEnumerable <IMessageListener> > StartListeningAsync( IConfiguration configuration, IServiceDefinition serviceDefinition, IDictionary <IEventDefinition, IConfiguration> eventConfigMap, CancellationToken ct) { // TODO: there are many scenarios that are not supported by the following code. // For example, exchange's connection is different from services' queues. var baseConnectionSettings = new ConnectionSettings(); configuration.Bind(baseConnectionSettings); var baseConnection = _connectionManager.GetConnection(baseConnectionSettings); var baseChannel = baseConnection.CreateModel(); foreach (var eventDefinition in serviceDefinition.Events) { if (!eventConfigMap.TryGetValue(eventDefinition, out var eventConfiguration)) { eventConfiguration = configuration; } var listenerSettings = RabbitMQCommunicationMethod.CreateEventsDefaultSettings(); eventConfiguration.Bind(listenerSettings); var exchangeName = listenerSettings.ExchangeName .Replace("{serviceName}", serviceDefinition.Name) .Replace("{eventName}", eventDefinition.Name); // TODO: declare once? what's the penalty? baseChannel.ExchangeDeclare( exchangeName, type: "fanout", durable: true, autoDelete: false, arguments: null); var eventDesc = new EventDescriptor { Service = new ServiceId { Name = serviceDefinition.Name }, Event = _eventIdProvider.GetId(eventDefinition.EventInfo) }; foreach (var subscriber in _eventSubscriber.GetSubscribers(eventDesc)) { if (!_serviceResolver.TryResolve(subscriber.Service, out var subscriberServiceReference)) { continue; } if (!_methodResolver.TryResolve(subscriberServiceReference.Definition, subscriber.Method, out var subscriberMethodReference)) { continue; } var subscriberMethodConfiguration = _communicationModelConfiguration.GetMethodConfiguration(subscriberMethodReference.Definition, "communication"); var subscriberSettings = RabbitMQCommunicationMethod.CreateMethodsDefaultSettings(); subscriberMethodConfiguration.Bind(subscriberSettings); var subscriberQueueName = subscriberSettings.QueueName .Replace("{serviceName}", subscriberServiceReference.Definition.Name) .Replace("{methodName}", subscriberMethodReference.Definition.Name); // TODO: declare once? what's the penalty? baseChannel.QueueBind( queue: subscriberQueueName, exchange: exchangeName, routingKey: "", arguments: null); } } // No direct listeners to RabbitMQ Exchanges, just configure exchange-queue bindings. // TODO: if events (or subscribers) use a different connection, // need to create a queue and a listener in that RabbitMQ instance. return(Task.FromResult <IEnumerable <IMessageListener> >(Array.Empty <IMessageListener>())); }
public async Task StartAsync(CancellationToken ct) { foreach (var serviceDefinition in _communicationModel.Services) { if (serviceDefinition.Type == ServiceType.External) { var serviceConfig = _communicationModelConfiguration.GetEventsConfiguration(serviceDefinition, CommunicationSectionName); var serviceCommunicationType = GetCommunicationType(serviceConfig); var serviceId = new ServiceId { Name = serviceDefinition.Name }; var anySubscriberToAnyEvent = false; var eventOverridesMap = new Dictionary <string, Dictionary <IEventDefinition, IConfiguration> >(StringComparer.OrdinalIgnoreCase); foreach (var eventDefinition in serviceDefinition.Events) { var eventId = _eventIdProvider.GetId(eventDefinition.EventInfo); var eventDesc = new EventDescriptor { Service = serviceId, Event = eventId }; var subscribers = _eventSubscriber.GetSubscribers(eventDesc).ToList(); if (subscribers.Count == 0) { continue; } var anySubscriberToThisEvent = false; foreach (var subscriber in subscribers) { if (_serviceResolver.TryResolve(subscriber.Service, out _)) { anySubscriberToThisEvent = true; anySubscriberToAnyEvent = true; break; } } if (!anySubscriberToThisEvent) { continue; } if (_communicationModelConfiguration .GetEventOverrideLevels(eventDefinition, CommunicationSectionName) .HasFlag(ConfigOverrideLevels.Primitive)) { var eventConfig = _communicationModelConfiguration.GetEventConfiguration(eventDefinition); var eventCommunicationType = GetCommunicationType(eventConfig); if (!eventOverridesMap.TryGetValue(eventCommunicationType, out var configMap)) { configMap = new Dictionary <IEventDefinition, IConfiguration>(); eventOverridesMap.Add(eventCommunicationType, configMap); } configMap.Add(eventDefinition, eventConfig); } } if (anySubscriberToAnyEvent) { if (!eventOverridesMap.TryGetValue(serviceCommunicationType, out var configMap)) { configMap = new Dictionary <IEventDefinition, IConfiguration>(); } await StartListeningEventsAsync(serviceCommunicationType, serviceDefinition, serviceConfig, configMap, ct); var extraCommTypes = eventOverridesMap.Keys.Where(c => !string.Equals(c, serviceCommunicationType, StringComparison.OrdinalIgnoreCase)); foreach (var extraCommType in extraCommTypes) { configMap = eventOverridesMap[extraCommType]; await StartListeningEventsAsync(extraCommType, serviceDefinition, serviceConfig, configMap, ct); } } } else { var methodOverridesMap = new Dictionary <string, Dictionary <IMethodDefinition, IConfiguration> >(StringComparer.OrdinalIgnoreCase); var eventOverridesMap = new Dictionary <string, Dictionary <IEventDefinition, IConfiguration> >(StringComparer.OrdinalIgnoreCase); foreach (var methodDefinition in serviceDefinition.Methods) { if (_communicationModelConfiguration .GetMethodOverrideLevels(methodDefinition, CommunicationSectionName) .HasFlag(ConfigOverrideLevels.Primitive)) { var methodConfig = _communicationModelConfiguration.GetMethodConfiguration(methodDefinition); var methodCommunicationType = GetCommunicationType(methodConfig); if (!methodOverridesMap.TryGetValue(methodCommunicationType, out var configMap)) { configMap = new Dictionary <IMethodDefinition, IConfiguration>(); methodOverridesMap.Add(methodCommunicationType, configMap); } configMap.Add(methodDefinition, methodConfig); } } foreach (var eventDefinition in serviceDefinition.Events) { if (_communicationModelConfiguration .GetEventsOverrideLevels(serviceDefinition, CommunicationSectionName) .HasFlag(ConfigOverrideLevels.Primitive)) { var eventConfig = _communicationModelConfiguration.GetEventConfiguration(eventDefinition); var eventCommunicationType = GetCommunicationType(eventConfig); if (!eventOverridesMap.TryGetValue(eventCommunicationType, out var configMap)) { configMap = new Dictionary <IEventDefinition, IConfiguration>(); eventOverridesMap.Add(eventCommunicationType, configMap); } configMap.Add(eventDefinition, eventConfig); } } var hasQueriesOverride = (_communicationModelConfiguration .GetQueriesOverrideLevels(serviceDefinition, CommunicationSectionName) & (ConfigOverrideLevels.BasePrimitives | ConfigOverrideLevels.ServiceTypePrimitives | ConfigOverrideLevels.ServicePrimitives)) != default; var hasCommandsOverride = (_communicationModelConfiguration .GetCommandsOverrideLevels(serviceDefinition, CommunicationSectionName) & (ConfigOverrideLevels.BasePrimitives | ConfigOverrideLevels.ServiceTypePrimitives | ConfigOverrideLevels.ServicePrimitives)) != default; if (hasQueriesOverride || hasCommandsOverride) { var allQueriesConfig = _communicationModelConfiguration.GetQueriesConfiguration(serviceDefinition, CommunicationSectionName); var allQueriesCommunicationType = GetCommunicationType(allQueriesConfig); if (!methodOverridesMap.TryGetValue(allQueriesCommunicationType, out var methodConfigMap)) { methodConfigMap = new Dictionary <IMethodDefinition, IConfiguration>(); } await StartHadlingMethodsAsync(allQueriesCommunicationType, serviceDefinition, allQueriesConfig, methodConfigMap, ct); var allCommandsConfig = _communicationModelConfiguration.GetCommandsConfiguration(serviceDefinition, CommunicationSectionName); var allCommandsCommunicationType = GetCommunicationType(allCommandsConfig); if (!methodOverridesMap.TryGetValue(allCommandsCommunicationType, out methodConfigMap)) { methodConfigMap = new Dictionary <IMethodDefinition, IConfiguration>(); } await StartHadlingMethodsAsync(allCommandsCommunicationType, serviceDefinition, allCommandsConfig, methodConfigMap, ct); var methodsExtraCommTypes = methodOverridesMap.Keys.Where(c => !string.Equals(c, allQueriesCommunicationType, StringComparison.OrdinalIgnoreCase) && !string.Equals(c, allCommandsCommunicationType, StringComparison.OrdinalIgnoreCase)); foreach (var methodExtraCommType in methodsExtraCommTypes) { methodConfigMap = methodOverridesMap[methodExtraCommType]; var queryConfigMap = new Dictionary <IMethodDefinition, IConfiguration>(); var commandConfigMap = new Dictionary <IMethodDefinition, IConfiguration>(); foreach (var pair in methodConfigMap) { if (pair.Key.IsQuery) { queryConfigMap.Add(pair.Key, pair.Value); } else { commandConfigMap.Add(pair.Key, pair.Value); } } if (queryConfigMap.Count > 0) { await StartHadlingMethodsAsync(methodExtraCommType, serviceDefinition, allQueriesConfig, queryConfigMap, ct); } if (commandConfigMap.Count > 0) { await StartHadlingMethodsAsync(methodExtraCommType, serviceDefinition, allCommandsConfig, commandConfigMap, ct); } } } else { var serviceConfig = _communicationModelConfiguration.GetServiceConfiguration(serviceDefinition, CommunicationSectionName); var serviceCommunicationType = GetCommunicationType(serviceConfig); if (!methodOverridesMap.TryGetValue(serviceCommunicationType, out var methodConfigMap)) { methodConfigMap = new Dictionary <IMethodDefinition, IConfiguration>(); } await StartHadlingMethodsAsync(serviceCommunicationType, serviceDefinition, serviceConfig, methodConfigMap, ct); var methodsExtraCommTypes = methodOverridesMap.Keys.Where(c => !string.Equals(c, serviceCommunicationType, StringComparison.OrdinalIgnoreCase)); foreach (var methodExtraCommType in methodsExtraCommTypes) { methodConfigMap = methodOverridesMap[methodExtraCommType]; await StartHadlingMethodsAsync(methodExtraCommType, serviceDefinition, serviceConfig, methodConfigMap, ct); } } var allEventsConfig = _communicationModelConfiguration.GetEventsConfiguration(serviceDefinition, CommunicationSectionName); var allEventsCommunicationType = GetCommunicationType(allEventsConfig); if (!eventOverridesMap.TryGetValue(allEventsCommunicationType, out var eventConfigMap)) { eventConfigMap = new Dictionary <IEventDefinition, IConfiguration>(); } await StartListeningEventsAsync(allEventsCommunicationType, serviceDefinition, allEventsConfig, eventConfigMap, ct); var eventsExtraCommTypes = eventOverridesMap.Keys.Where(c => !string.Equals(c, allEventsCommunicationType, StringComparison.OrdinalIgnoreCase)); foreach (var eventExtraCommType in eventsExtraCommTypes) { eventConfigMap = eventOverridesMap[eventExtraCommType]; await StartListeningEventsAsync(eventExtraCommType, serviceDefinition, allEventsConfig, eventConfigMap, ct); } } } }