Ejemplo n.º 1
0
        public async Task StartConsumeAsync_Test(bool autoDelete)
        {
            int maxConcurrentMessages = 100;
            var queueName             = RabbitMapper.GetQueueName(_serviceName, _topicName);

            var consumer = new RabbitConsumer(_connection, _serviceName, _topicName, MessageHandler,
                                              () => { }, false, maxConcurrentMessages, _options, _logger);

            // first start
            await consumer.StartConsumeAsync(_cancellationTokenSource.Token);

            A.CallTo(() => _rabbitChannel.BasicQos(0, (ushort)maxConcurrentMessages, false))
            .MustHaveHappenedOnceExactly();
            A.CallTo(() => _rabbitChannel.QueueDeclare(queueName, true, false, false, null))
            .MustHaveHappenedOnceExactly();

            A.CallTo(() => _rabbitChannel.ExchangeDeclare(_options.Exchange, ExchangeType.Direct, true, false, null))
            .MustHaveHappenedOnceExactly();

            A.CallTo(() => _rabbitChannel.QueueBind(queueName, _options.Exchange, _topicName, null))
            .MustHaveHappenedOnceExactly();
            A.CallTo(() =>
                     _rabbitChannel.BasicConsume(queueName, false, "", false, false, null,
                                                 A <AsyncEventingBasicConsumer> .Ignored))
            .MustHaveHappenedOnceExactly();
            Assert.IsTrue(consumer.IsStarted);

            // does not repeat execution if started multiple times
            await consumer.StartConsumeAsync(_cancellationTokenSource.Token);

            A.CallTo(() => _rabbitChannel.QueueDeclare(queueName, true, false, false, null))
            .MustHaveHappenedOnceExactly();
            Assert.IsTrue(consumer.IsStarted);
        }
Ejemplo n.º 2
0
        public RabbitConsumer(IRabbitFactoryConnection connection,
                              string serviceName, string topicName,
                              Func <GateContext, CancellationToken, Task> messageHandler,
                              Action abortedHandler,
                              bool autoDelete,
                              int maxConcurrentMessages,
                              RabbitOptions options, ILogger logger)
        {
            ServiceName = string.IsNullOrEmpty(serviceName) ?
                          throw new ArgumentException("ServiceName null or empty", nameof(serviceName)) : serviceName;
            TopicName = string.IsNullOrEmpty(topicName) ?
                        throw new ArgumentException("TopicName null or empty", nameof(topicName)) : topicName;
            AutoDelete            = autoDelete;
            MaxConcurrentMessages = maxConcurrentMessages;
            _messageHandler       = messageHandler ?? throw new ArgumentNullException(nameof(messageHandler));

            if (abortedHandler == null)
            {
                throw new ArgumentNullException(nameof(abortedHandler));
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));

            var queueName  = RabbitMapper.GetQueueName(ServiceName, TopicName);
            var routingKey = RabbitMapper.GetRoutingKey(TopicName);

            _consumer = new RabbitInternalConsumer(connection, options.Exchange, queueName, routingKey, AutoDelete, (ushort)MaxConcurrentMessages, HandleMessage,
                                                   abortedHandler);
        }
Ejemplo n.º 3
0
        public Task <byte[]> RequestAsync(string serviceName, string topicName, byte[] message,
                                          int requestTimeoutInSeconds,
                                          CancellationToken cancellationToken = default)
        {
            if (string.IsNullOrEmpty(serviceName))
            {
                throw new ArgumentException("ServiceName is null or empty", nameof(serviceName));
            }

            if (string.IsNullOrEmpty(topicName))
            {
                throw new ArgumentException("TopicName is null or empty", nameof(topicName));
            }

            var correlationId = Guid.NewGuid().ToString();
            var tcs           = new TaskCompletionSource <byte[]>();


            lock (_rpcAsyncLock)
            {
                if (_rpcChannel == null)
                {
                    var connection = _connection.GetConnection();
                    _rpcChannel = connection.CreateModel();
                    var consumer = new EventingBasicConsumer(_rpcChannel);
                    _rpcChannel.BasicConsume(consumer, ReplyToQueueName, true);
                    consumer.Received += (sender, ea) => HandleResponse(ea.BasicProperties.CorrelationId, ea.Body.ToArray());
                }

                var props = _rpcChannel.CreateBasicProperties();
                props.ReplyTo       = ReplyToQueueName;
                props.DeliveryMode  = 1;                                           // non persistent delivery mode
                props.Expiration    = (requestTimeoutInSeconds * 1000).ToString(); // timeout in milliseconds as string
                props.CorrelationId = correlationId;

                Timer timeoutTimer = null;
                timeoutTimer = new Timer(state =>
                {
                    _waitingResponses.TryRemove(correlationId, out _);
                    tcs.TrySetException(new TimeoutException($"Timeout waiting response for CorrelationId [{correlationId}]"));
                    timeoutTimer?.Dispose();
                }, null, TimeSpan.FromSeconds(requestTimeoutInSeconds), TimeSpan.FromMilliseconds(-1));

                cancellationToken.Register(() => {
                    _waitingResponses.TryRemove(correlationId, out _);
                    tcs.TrySetException(new OperationCanceledException($"Waiting response canceled for CorrelationId [{correlationId}]"));
                    timeoutTimer?.Dispose();
                });

                _waitingResponses.TryAdd(correlationId, msg => {
                    if (_waitingResponses.TryRemove(correlationId, out _))
                    {
                        tcs.TrySetResult(msg);
                    }
                    timeoutTimer?.Dispose();
                });

                _logger.LogDebug("Publishing request for service [{}] with correlationId [{}]", serviceName, correlationId);
                var queueName = RabbitMapper.GetQueueName(serviceName, topicName);
                _rpcChannel.BasicPublish("", queueName, props, message);
            }

            return(tcs.Task);
        }