Ejemplo n.º 1
0
    public Task PublishAsync <TEvent>(TEvent @event) where TEvent : EventBase
    {
        Check.NotNull(@event, nameof(@event));

        if (!_connection.IsConnected)
        {
            _connection.TryConnect();
        }

        var policy = Policy.Handle <BrokerUnreachableException>()
                     .Or <SocketException>()
                     .WaitAndRetry(_options.RetryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
                                   (ex, time) =>
        {
            _logger.LogWarning(ex,
                               $"Could not publish event: {@event.EventId} after {time.TotalSeconds:n1}s ({ex.Message})");
        });

        IModel channel = null;

        try
        {
            var eventName = @event.GetType().GetEventName();
            var bytes     = Encoding.UTF8.GetBytes(Default.JsonHelper.Serialize(@event));

            policy.Execute(() =>
            {
                if (channel == null)
                {
                    channel = _connection.CreateModel();
                    _logger.LogTrace($"Declaring RabbitMQ exchange to publish event: {@event.EventId}");

                    channel.ExchangeDeclare(_options.Exchange, "direct");
                }

                var properties          = channel.CreateBasicProperties();
                properties.DeliveryMode = 2; // persistent

                _logger.LogTrace($"Publishing event to RabbitMQ: {@event.EventId}");

                channel.BasicPublish(_options.Exchange, eventName, true, properties, bytes);
                channel.Dispose();
            });
        }
        finally
        {
            // channel.Close();
            channel?.Dispose();
        }

        return(Task.CompletedTask);
    }
        public override async ValueTask Publish(IIntegrationEvent @event)
        {
            if (!PersistentConnection.IsConnected)
            {
                PersistentConnection.TryConnect();
            }

            var policy = Policy.Handle <BrokerUnreachableException>()
                         .Or <SocketException>()
                         .Or <Exception>()
                         .WaitAndRetryForever(retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
            {
                Logger.LogWarning(ex.ToString());
            });

            using var channel = PersistentConnection.CreateModel();
            var routingKey = @event.RoutingKey;

            channel.ExchangeDeclare(ExchangeDeclareParameters.ExchangeName, ExchangeDeclareParameters.ExchangeType, ExchangeDeclareParameters.ExchangeDurable, ExchangeDeclareParameters.ExchangeAutoDelete);

            await using var ms = new MemoryStream();
            Serializer.Serialize(ms, @event);
            var body = ms.ToArray();

            policy.Execute(() =>
            {
                var properties           = channel.CreateBasicProperties();
                properties.DeliveryMode  = 1; //2 = persistent, write on disk
                properties.CorrelationId = _correlationId;
                properties.ReplyTo       = _queueNameReply;
                channel.BasicPublish(ExchangeDeclareParameters.ExchangeName, routingKey, true, properties, body);
            });
        }
Ejemplo n.º 3
0
        private void SubsManager_OnEventReplyRemoved(object sender, string eventName)
        {
            if (!PersistentConnection.IsConnected)
            {
                PersistentConnection.TryConnect();
            }

            using (var channel = PersistentConnection.CreateModel())
            {
                channel.QueueUnbind(QueueName, ExchangeDeclareParameters.ExchangeName, eventName);

                channel.QueueUnbind(_queueNameReply, ExchangeDeclareParameters.ExchangeName, eventName);
            }

            if (!SubsManager.IsReplyEmpty)
            {
                return;
            }

            QueueName = string.Empty;
            ConsumerChannel?.Close();

            //ToDo

            _queueNameReply = string.Empty;
            _consumerChannelReply?.Close();
        }
        private void DoInternalSubscriptionRpc(string eventName, string eventNameResult)
        {
            var containsKey = SubsManager.HasSubscriptionsForEvent(eventName);

            if (containsKey)
            {
                return;
            }
            if (!PersistentConnection.IsConnected)
            {
                PersistentConnection.TryConnect();
            }

            using var channel = PersistentConnection.CreateModel();
            channel.QueueBind(QueueName, ExchangeDeclareParameters.ExchangeName, eventName);
            channel.QueueBind(_queueNameReply, ExchangeDeclareParameters.ExchangeName, eventNameResult);
        }
Ejemplo n.º 5
0
        public async Task <TR> CallAsync <TR>(IIntegrationEvent @event, CancellationToken cancellationToken = default)
            where TR : IIntegrationEventReply
        {
            if (!PersistentConnection.IsConnected)
            {
                PersistentConnection.TryConnect();
            }

            var policy = Policy.Handle <BrokerUnreachableException>()
                         .Or <SocketException>()
                         .Or <Exception>()
                         .WaitAndRetryForever(retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
            {
                Logger.LogWarning(ex.ToString());
            });

            using var channel = PersistentConnection.CreateModel();
            var routingKey = @event.RoutingKey;

            channel.ExchangeDeclare(ExchangeDeclareParameters.ExchangeName, ExchangeDeclareParameters.ExchangeType, ExchangeDeclareParameters.ExchangeDurable, ExchangeDeclareParameters.ExchangeAutoDelete);

            await using var ms = new MemoryStream();
            Serializer.Serialize(ms, @event);
            var body          = ms.ToArray();
            var correlationId = Guid.NewGuid().ToString();
            var tcs           = new TaskCompletionSource <dynamic>();

            _callbackMapper.TryAdd(correlationId, tcs);

            policy.Execute(() =>
            {
                var properties           = channel.CreateBasicProperties();
                properties.DeliveryMode  = 1; //2 = persistent, write on disk
                properties.CorrelationId = correlationId;
                properties.ReplyTo       = QueueName;
                channel.BasicPublish(ExchangeDeclareParameters.ExchangeName, routingKey, true, properties, body);
            });

            cancellationToken.Register(() => _callbackMapper.TryRemove(correlationId, out var tmp));
            return(await tcs.Task);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="services"></param>
        /// <param name="connectionString"></param>
        /// <param name="eventBusOptionAction"></param>
        /// <returns></returns>
        public static void AddRabbitMQEventBus(this Container container,
                                               string connectionString,
                                               Action <ConnectionConfigurationBuild> eventBusOptionAction)
        {
            ConnectionConfiguration      configuration      = new ConnectionConfiguration();
            ConnectionConfigurationBuild configurationBuild = new ConnectionConfigurationBuild(configuration);

            eventBusOptionAction?.Invoke(configurationBuild);

            container.RegisterSingleton <IPersistentConnection>(() =>
            {
                IConnectionFactory factory = new ConnectionFactory
                {
                    AutomaticRecoveryEnabled = configuration.AutomaticRecoveryEnabled,
                    NetworkRecoveryInterval  = configuration.NetworkRecoveryInterval,
                    Uri = new Uri(connectionString),
                };

                var connection = new PersistentConnection(configuration, factory);

                connection.TryConnect();

                return(connection);
            });

            container.RegisterSingleton <IEventHandlerModuleFactory, EventHandlerModuleFactory>();
            container.RegisterSingleton <RabbitMqCore, RabbitMqCore>();

            foreach (Type mType in typeof(IEvent).GetAssemblies())
            {
                container.Register(mType);

                foreach (Type hType in typeof(IEventHandler <>).GetMakeGenericType(mType))
                {
                    container.Register(hType);
                }
            }
        }
        private IModel CreateConsumerChannelReply(CancellationToken cancel = default)
        {
            if (!PersistentConnection.IsConnected)
            {
                PersistentConnection.TryConnect();
            }

            var channel = PersistentConnection.CreateModel();

            channel.ExchangeDeclare(ExchangeDeclareParameters.ExchangeName, ExchangeDeclareParameters.ExchangeType, ExchangeDeclareParameters.ExchangeDurable, ExchangeDeclareParameters.ExchangeAutoDelete);

            channel.QueueDeclare(_queueNameReply, QueueDeclareParameters.QueueDurable, QueueDeclareParameters.QueueExclusive, QueueDeclareParameters.QueueAutoDelete, null);
            channel.BasicQos(0, 1, false);

            channel.CallbackException += (sender, ea) =>
            {
                Logger.LogError("CallbackException Rpc: " + ea.Exception.Message);
                _consumerChannelReply.Dispose();
                _consumerChannelReply = CreateConsumerChannelReply(cancel);
                StartBasicConsumeReply();
            };

            return(channel);
        }
        public async Task <TIntegrationEventReply> CallAsync <TIntegrationEventReply>(IIntegrationEvent @event, CancellationToken cancellationToken = default)
            where TIntegrationEventReply : IIntegrationEventReply
        {
            try
            {
                if (!PersistentConnection.IsConnected)
                {
                    PersistentConnection.TryConnect();
                }

                var policy = Policy.Handle <BrokerUnreachableException>()
                             .Or <SocketException>()
                             .Or <Exception>()
                             .WaitAndRetryForever(retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
                {
                    Logger.LogWarning(ex.ToString());
                });

                var correlationId = Guid.NewGuid().ToString();

                var tcs = new TaskCompletionSource <dynamic>(TaskCreationOptions.RunContinuationsAsynchronously);
                _callbackMapper.TryAdd(correlationId, tcs);

                using (var channel = PersistentConnection.CreateModel())
                {
                    var routingKey = @event.RoutingKey;

                    channel.ExchangeDeclare(ExchangeDeclareParameters.ExchangeName,
                                            ExchangeDeclareParameters.ExchangeType,
                                            ExchangeDeclareParameters.ExchangeDurable, ExchangeDeclareParameters.ExchangeAutoDelete);

                    await using var ms = new MemoryStream();

                    Serializer.Serialize(ms, @event);
                    var body = ms.ToArray();

                    policy.Execute(() =>
                    {
                        var properties = channel.CreateBasicProperties();
                        //properties.ContentType = "application/protobuf";
                        properties.DeliveryMode  = 1; //2 = persistent, write on disk
                        properties.CorrelationId = correlationId;
                        //properties.ReplyTo = QueueName;
                        properties.ReplyTo = _queueNameReply; //ToDo

                        channel.BasicPublish(ExchangeDeclareParameters.ExchangeName, routingKey, true, properties,
                                             body);
                    });
                }

                cancellationToken.Register(() => _callbackMapper.TryRemove(correlationId, out var tmp));

                var result = await tcs.Task.ConfigureAwait(false);

                return((TIntegrationEventReply)result);
            }
            catch (Exception ex)
            {
                Logger.LogError("CallAsync: " + ex.Message + " " + ex.StackTrace);
            }
            return(default);