public void When_requeueing_a_message()
        {
            _producer.Send(_message);
            var channel = _channelFactory.CreateChannel(_subscription);
            var message = channel.Receive(2000);

            channel.Requeue(message, 100);

            var requeuedMessage = channel.Receive(1000);

            //clear the queue
            channel.Acknowledge(requeuedMessage);

            requeuedMessage.Body.Value.Should().Be(message.Body.Value);
        }
Exemplo n.º 2
0
        public void When_requeueing_a_message()
        {
            ((IAmAMessageProducerSync)_producerRegistry.LookupBy(_topic)).Send(_message);
            var channel = _channelFactory.CreateChannel(_subscription);
            var message = channel.Receive(2000);

            channel.Requeue(message, 100);

            var requeuedMessage = channel.Receive(1000);

            //clear the queue
            channel.Acknowledge(requeuedMessage);

            requeuedMessage.Body.Value.Should().Be(message.Body.Value);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Uses the Request-Reply messaging approach to send a message to another server and block awaiting a reply.
        /// The message is placed into a message queue but not into the outbox.
        /// An ephemeral reply queue is created, and its name used to set the reply address for the response. We produce
        /// a queue per exchange, to simplify correlating send and receive.
        /// The response is directed to a registered handler.
        /// Because the operation blocks, there is a mandatory timeout
        /// </summary>
        /// <param name="request">What message do we want a reply to</param>
        /// <param name="timeOutInMilliseconds">The call blocks, so we must time out</param>
        /// <exception cref="NotImplementedException"></exception>
        public TResponse Call <T, TResponse>(T request, int timeOutInMilliseconds)
            where T : class, ICall where TResponse : class, IResponse
        {
            if (timeOutInMilliseconds <= 0)
            {
                throw new InvalidOperationException("Timeout to a call method must have a duration greater than zero");
            }

            var outMessageMapper = _mapperRegistry.Get <T>();

            if (outMessageMapper == null)
            {
                throw new ArgumentOutOfRangeException(
                          $"No message mapper registered for messages of type: {typeof(T)}");
            }

            var inMessageMapper = _mapperRegistry.Get <TResponse>();

            if (inMessageMapper == null)
            {
                throw new ArgumentOutOfRangeException(
                          $"No message mapper registered for messages of type: {typeof(T)}");
            }

            //create a reply queue via creating a consumer - we use random identifiers as we will destroy
            var channelName = Guid.NewGuid();
            var routingKey  = channelName.ToString();

            using (var responseChannel =
                       _responseChannelFactory.CreateChannel(
                           new Connection(
                               typeof(TResponse),
                               channelName: new ChannelName(channelName.ToString()),
                               routingKey: new RoutingKey(routingKey))))
            {
                _logger.Value.InfoFormat("Create reply queue for topic {0}", routingKey);
                request.ReplyAddress.Topic         = routingKey;
                request.ReplyAddress.CorrelationId = channelName;

                //we do this to create the channel on the broker, or we won't have anything to send to; we
                //retry in case the connection is poor. An alternative would be to extract the code from
                //the channel to create the connection, but this does not do much on a new queue
                Retry(() => responseChannel.Purge());

                var outMessage = outMessageMapper.MapToMessage(request);

                //We don't store the message, if we continue to fail further retry is left to the sender
                _logger.Value.DebugFormat("Sending request  with routingkey {0}", routingKey);
                Retry(() => _messageProducer.Send(outMessage));

                Message responseMessage = null;

                //now we block on the receiver to try and get the message, until timeout.
                _logger.Value.DebugFormat("Awaiting response on {0}", routingKey);
                Retry(() => responseMessage = responseChannel.Receive(timeOutInMilliseconds));

                TResponse response = default(TResponse);
                if (responseMessage.Header.MessageType != MessageType.MT_NONE)
                {
                    _logger.Value.DebugFormat("Reply received from {0}", routingKey);
                    //map to request is map to a response, but it is a request from consumer point of view. Confusing, but...
                    response = inMessageMapper.MapToRequest(responseMessage);
                    Send(response);
                }

                _logger.Value.InfoFormat("Deleting queue for routingkey: {0}", routingKey);

                return(response);
            } //clean up everything at this point, whatever happens
        }