Exemple #1
0
        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.");
            }
        }
Exemple #2
0
        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);
                    }
                }
            }
        }