public void TestDefaultConsumerCount()
 {
     var container = new SimpleMessageListenerContainer(new SingleConnectionFactory());
     container.MessageListener = new MessageListenerAdapter(this);
     container.QueueNames = new string[] { "foo" };
     container.AutoStartup = false;
     container.AfterPropertiesSet();
     Assert.AreEqual(1, ReflectionUtils.GetInstanceFieldValue(container, "concurrentConsumers"));
 }
        public void TestListenerWithManualAckNonTransactional()
        {
            var latch = new CountdownEvent(this.messageCount);
            this.container = this.CreateContainer(new TestListener(latch));
            for (var i = 0; i < this.messageCount; i++)
            {
                this.template.ConvertAndSend(queue.Name, i + "foo");
            }

            var timeout = Math.Min(1 + messageCount / (4 * concurrentConsumers), 30);
            logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
            var waited = latch.Wait(timeout * 1000);
            Assert.True(waited, "Timed out waiting for message");
            Assert.Null(this.template.ReceiveAndConvert(queue.Name));
        }
        public void TestListenerTransactionalFails()
        {
            this.transactional = true;
            var latch = new CountDownLatch(this.messageCount);
            this.container = this.CreateContainer(new TxTestListener(latch, true, this));
            for (var i = 0; i < this.txSize; i++)
            {
                this.template.ConvertAndSend(this.queue.Name, i + "foo");
            }

            var timeout = Math.Min(1 + this.messageCount / (4 * this.concurrentConsumers), 30);
            logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
            var waited = latch.Await(new TimeSpan(0, 0, 0, timeout));
            Assert.True(waited, "Timed out waiting for message");
            Assert.Null(this.template.ReceiveAndConvert(this.queue.Name));
        }
        public void TestInconsistentAcknowledgeConfiguration()
        {
            var container = new SimpleMessageListenerContainer(new SingleConnectionFactory());
            container.MessageListener = new MessageListenerAdapter(this);
            container.QueueNames = new[] { "foo" };
            container.ChannelTransacted = true;
            container.AcknowledgeMode = AcknowledgeModeUtils.AcknowledgeMode.None;

            try
            {
                container.AfterPropertiesSet();
            }
            catch (Exception e)
            {
                Assert.True(e is InvalidOperationException);
            }
        }
Exemplo n.º 5
0
        private void ReceiveAsync()
        {
            SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
            container.ConnectionFactory = this.connectionFactory;
            container.Queue = TestConstants.QUEUE_NAME;
            container.ConcurrentConsumers = 5;

            MessageListenerAdapter adapter = new MessageListenerAdapter();
            adapter.HandlerObject = new PocoHandler();
            container.MessageListener = adapter;
            container.AfterPropertiesSet();
            container.Start();
            Console.WriteLine("Main execution thread sleeping...");
            Thread.Sleep(30000);
            Console.WriteLine("Main execution thread exiting.");
            container.Stop();
            container.Shutdown();
        }
        /// <summary>
        /// Does the test.
        /// </summary>
        /// <param name="messageCount">The message count.</param>
        /// <param name="errorHandler">The error handler.</param>
        /// <param name="latch">The latch.</param>
        /// <param name="listener">The listener.</param>
        /// <remarks></remarks>
        public void DoTest(int messageCount, IErrorHandler errorHandler, CountdownEvent latch, object listener)
        {
            var concurrentConsumers = 1;
            var template = this.CreateTemplate(concurrentConsumers);

            // Send messages to the queue
            for (var i = 0; i < messageCount; i++)
            {
                template.ConvertAndSend(queue.Name, i + "foo");
            }

            var container = new SimpleMessageListenerContainer(template.ConnectionFactory);
            container.MessageListener = listener;
            container.AcknowledgeMode = AcknowledgeModeUtils.AcknowledgeMode.NONE;
            container.IsChannelTransacted = false;
            container.ConcurrentConsumers = concurrentConsumers;

            container.PrefetchCount = messageCount;
            container.TxSize = messageCount;
            container.QueueNames = new string[] { queue.Name };
            container.ErrorHandler = errorHandler;
            container.AfterPropertiesSet();
            container.Start();

            var waited = latch.Wait(500);
            if (messageCount > 1)
            {
                Assert.True(waited, "Expected to receive all messages before stop");
            }

            try
            {
                Assert.Null(template.ReceiveAndConvert(queue.Name));
            }
            finally
            {
                container.Shutdown();
            }
        }
        public void TestListenerSendsMessageAndThenRollback()
        {
            var connectionFactory = this.CreateConnectionFactory();
            var template = new RabbitTemplate(connectionFactory);
            new RabbitAdmin(connectionFactory).DeclareQueue(sendQueue);

            this.acknowledgeMode = AcknowledgeModeUtils.AcknowledgeMode.Auto;
            this.transactional = true;

            var latch = new CountdownEvent(1);
            this.container = this.CreateContainer(queue.Name, new ChannelSenderListener(sendQueue.Name, latch, true), connectionFactory);
            template.ConvertAndSend(queue.Name, "foo");

            var timeout = this.GetTimeout();
            Logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
            var waited = latch.Wait(timeout * 1000);
            Assert.True(waited, "Timed out waiting for message");

            this.container.Stop();
            Thread.Sleep(200);

            // Foo message is redelivered
            Assert.AreEqual("foo", template.ReceiveAndConvert(queue.Name));

            // Sending of bar message is also rolled back
            Assert.Null(template.ReceiveAndConvert(sendQueue.Name));
        }
        public void TestListenerSendsMessageAndThenContainerCommits()
        {
            var connectionFactory = this.CreateConnectionFactory();
            var template = new RabbitTemplate(connectionFactory);
            new RabbitAdmin(connectionFactory).DeclareQueue(sendQueue);

            this.acknowledgeMode = AcknowledgeModeUtils.AcknowledgeMode.Auto;
            this.transactional = true;

            var latch = new CountdownEvent(1);
            this.container = this.CreateContainer(queue.Name, new ChannelSenderListener(sendQueue.Name, latch, false), connectionFactory);
            template.ConvertAndSend(queue.Name, "foo");

            var timeout = this.GetTimeout();
            Logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
            var waited = latch.Wait(new TimeSpan(0, 0, timeout));
            Assert.True(waited, "Timed out waiting for message");

            Thread.Sleep(500);

            // All messages committed
            var bytes = (byte[])template.ReceiveAndConvert(sendQueue.Name);
            Assert.NotNull(bytes);
            Assert.AreEqual("bar", Encoding.UTF8.GetString(bytes));
            Assert.AreEqual(null, template.ReceiveAndConvert(queue.Name));
        }
 public AsyncMessageProcessingConsumer(QueueingBasicConsumer consumer,
     SimpleMessageListenerContainer messageListenerContainer)
 {
     this.consumer = consumer;
     this.messageListenerContainer = messageListenerContainer;
 }
 private SimpleMessageListenerContainer CreateContainer(object listener)
 {
     var container = new SimpleMessageListenerContainer(this.template.ConnectionFactory);
     container.MessageListener = new MessageListenerAdapter(listener);
     container.QueueNames = new[] { this.queue.Name };
     container.TxSize = this.txSize;
     container.PrefetchCount = this.txSize;
     container.ConcurrentConsumers = this.concurrentConsumers;
     container.ChannelTransacted = this.transactional;
     container.AcknowledgeMode = AcknowledgeModeUtils.AcknowledgeMode.Auto;
     container.AfterPropertiesSet();
     container.Start();
     return container;
 }
 /// <summary>Initializes a new instance of the <see cref="ContainerDelegate"/> class.</summary>
 /// <param name="outer">The outer.</param>
 public ContainerDelegate(SimpleMessageListenerContainer outer)
 {
     this.outer = outer;
 }
 public void TestSingleListenerDoesNotRecoverFromMissingQueue()
 {
     try
     {
         /*
          * A single listener sometimes doesn't have time to attempt to start before we ask it if it has failed, so this
          * is a good test of that potential bug.
          */
         this.concurrentConsumers = 1;
         var latch = new CountdownEvent(this.messageCount);
         this.container = this.CreateContainer("nonexistent", new VanillaListener(latch), this.CreateConnectionFactory());
     }
     catch (Exception e)
     {
         Assert.True(e is AmqpIllegalStateException);
     }
 }
        public void TestListenerRecoversAndTemplateSharesConnectionFactory()
        {
            var connectionFactory = this.CreateConnectionFactory();
            var template = new RabbitTemplate(connectionFactory);

            this.acknowledgeMode = AcknowledgeModeUtils.AcknowledgeMode.Manual;

            var latch = new CountdownEvent(this.messageCount);
            this.container = this.CreateContainer(queue.Name, new ManualAckListener(latch), connectionFactory);
            for (var i = 0; i < this.messageCount; i++)
            {
                template.ConvertAndSend(queue.Name, i + "foo");
            }

            var timeout = this.GetTimeout();
            Logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
            var waited = latch.Wait(new TimeSpan(0, 0, timeout));
            Assert.True(waited, "Timed out waiting for message");

            Assert.Null(template.ReceiveAndConvert(queue.Name));
        }
        /// <summary>Creates the container.</summary>
        /// <param name="listener">The listener.</param>
        /// <returns>The container.</returns>
        private SimpleMessageListenerContainer CreateContainer(object listener)
        {
            var container = new SimpleMessageListenerContainer(this.template.ConnectionFactory);
            container.MessageListener = listener;
            container.QueueNames = new[] { this.queue.Name };
            container.TxSize = this.txSize;
            container.PrefetchCount = this.txSize;
            container.ConcurrentConsumers = this.concurrentConsumers;
            container.ChannelTransacted = this.transactional;
            container.AcknowledgeMode = this.acknowledgeMode;
            if (this.externalTransaction)
            {
                container.TransactionManager = new IntegrationTestTransactionManager();
            }

            container.AfterPropertiesSet();
            container.Start();
            return container;
        }
        /// <summary>Does the listener with exception test.</summary>
        /// <param name="latch">The latch.</param>
        /// <param name="listener">The listener.</param>
        private void DoListenerWithExceptionTest(CountdownEvent latch, object listener)
        {
            this.container = this.CreateContainer(listener);
            if (this.acknowledgeMode.TransactionAllowed())
            {
                // Should only need one message if it is going to fail
                for (var i = 0; i < this.concurrentConsumers; i++)
                {
                    this.template.ConvertAndSend(this.queue.Name, i + "foo");
                }
            }
            else
            {
                for (var i = 0; i < this.messageCount; i++)
                {
                    this.template.ConvertAndSend(this.queue.Name, i + "foo");
                }
            }

            try
            {
                Logger.Debug(m => m("Waiting {0} seconds for messages to be received.", 5 + Math.Max(1, this.messageCount / 10)));
                var waited = latch.Wait(new TimeSpan(0, 0, 0, 5 + Math.Max(1, this.messageCount / 10)));
                Assert.True(waited, "Timed out waiting for message");
            }
            finally
            {
                // Wait for broker communication to finish before trying to stop
                // container
                Thread.Sleep(300);
                this.container.Shutdown();
                Thread.Sleep(300);
            }

            if (this.acknowledgeMode.TransactionAllowed())
            {
                Assert.NotNull(this.template.ReceiveAndConvert(this.queue.Name));
            }
            else
            {
                Assert.Null(this.template.ReceiveAndConvert(this.queue.Name));
            }
        }
        /// <summary>Does the sunny day test.</summary>
        /// <param name="latch">The latch.</param>
        /// <param name="listener">The listener.</param>
        private void DoSunnyDayTest(CountdownEvent latch, object listener)
        {
            this.container = this.CreateContainer(listener);
            for (var i = 0; i < this.messageCount; i++)
            {
                this.template.ConvertAndSend(this.queue.Name, i + "foo");
            }

            Logger.Debug(m => m("Waiting {0} seconds for messages to be received.", Math.Max(2, this.messageCount / 20)));
            var waited = latch.Wait(new TimeSpan(0, 0, 0, Math.Max(2, this.messageCount / 20)));
            Assert.True(waited, "Timed out waiting for message");
            Assert.Null(this.template.ReceiveAndConvert(this.queue.Name));
        }
        public void TestMessageListener()
        {
            var mockConnectionFactory = new Mock<ConnectionFactory>();
            var mockConnection = new Mock<IConnection>();
            var onlyChannel = new Mock<IModel>();
            onlyChannel.Setup(m => m.IsOpen).Returns(true);
            onlyChannel.Setup(m => m.CreateBasicProperties()).Returns(() => new BasicProperties());

            var cachingConnectionFactory = new CachingConnectionFactory(mockConnectionFactory.Object);

            mockConnectionFactory.Setup(m => m.CreateConnection()).Returns(mockConnection.Object);
            mockConnection.Setup(m => m.IsOpen).Returns(true);

            var tooManyChannels = new BlockingCollection<Exception>(1);
            var done = false;
            mockConnection.Setup(m => m.CreateModel()).Returns(
                () =>
                {
                    if (!done)
                    {
                        done = true;
                        return onlyChannel.Object;
                    }

                    tooManyChannels.Add(new Exception("More than one channel requested"));
                    var channel = new Mock<IModel>();
                    channel.Setup(m => m.IsOpen).Returns(true);
                    return channel.Object;
                });

            var consumer = new BlockingCollection<IBasicConsumer>(1);

            onlyChannel.Setup(m => m.BasicConsume(It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<IBasicConsumer>())).Callback<string, bool, IBasicConsumer>(
                (a1, a2, a3) => consumer.Add(a3));

            var commitLatch = new CountdownEvent(1);
            onlyChannel.Setup(m => m.TxCommit()).Callback(() => commitLatch.Signal());

            var latch = new CountdownEvent(1);
            var container = new SimpleMessageListenerContainer(cachingConnectionFactory);
            container.MessageListener = new Action<Message>(
                message =>
                {
                    var rabbitTemplate = new RabbitTemplate(cachingConnectionFactory);
                    rabbitTemplate.ChannelTransacted = true;

                    // should use same channel as container
                    rabbitTemplate.ConvertAndSend("foo", "bar", "baz");
                    latch.Signal();
                });
            container.QueueNames = new[] { "queue" };
            container.ChannelTransacted = true;
            container.ShutdownTimeout = 100;
            container.AfterPropertiesSet();
            container.Start();

            IBasicConsumer currentConsumer;
            consumer.TryTake(out currentConsumer, timeout);
            Assert.IsNotNull(currentConsumer, "Timed out getting consumer.");
            currentConsumer.HandleBasicDeliver("qux", 1, false, "foo", "bar", new BasicProperties(), new byte[] { 0 });

            Assert.IsTrue(latch.Wait(new TimeSpan(0, 0, 10)));

            var e = tooManyChannels.Count;
            if (e > 0)
            {
                throw tooManyChannels.Take();
            }

            mockConnection.Verify(m => m.CreateModel(), Times.Once());
            Assert.True(commitLatch.Wait(new TimeSpan(0, 0, 10)));
            onlyChannel.Verify(m => m.TxCommit(), Times.Once());
            onlyChannel.Verify(m => m.BasicPublish(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<IBasicProperties>(), It.IsAny<byte[]>()), Times.Once());

            // verify close() was never called on the channel
            var cachedChannelsTransactionalField = typeof(CachingConnectionFactory).GetField("cachedChannelsTransactional", BindingFlags.NonPublic | BindingFlags.Instance);
            var channels = (LinkedList<IChannelProxy>)cachedChannelsTransactionalField.GetValue(cachingConnectionFactory);
            Assert.AreEqual(0, channels.Count);

            container.Stop();
        }
        public void TestChannelAwareMessageListenerDontExpose()
        {
            var mockConnectionFactory = new Mock<ConnectionFactory>();
            var mockConnection = new Mock<IConnection>();
            var firstChannel = new Mock<IModel>();
            firstChannel.Setup(m => m.IsOpen).Returns(true);
            firstChannel.Setup(m => m.CreateBasicProperties()).Returns(() => new BasicProperties());

            var secondChannel = new Mock<IModel>();
            secondChannel.Setup(m => m.IsOpen).Returns(true);
            secondChannel.Setup(m => m.CreateBasicProperties()).Returns(() => new BasicProperties());

            var singleConnectionFactory = new SingleConnectionFactory(mockConnectionFactory.Object);

            mockConnectionFactory.Setup(m => m.CreateConnection()).Returns(mockConnection.Object);
            mockConnection.Setup(m => m.IsOpen).Returns(true);

            var tooManyChannels = new BlockingCollection<Exception>(1);
            var done = false;
            mockConnection.Setup(m => m.CreateModel()).Returns(
                () =>
                {
                    if (!done)
                    {
                        done = true;
                        return firstChannel.Object;
                    }

                    return secondChannel.Object;
                });

            var consumer = new BlockingCollection<IBasicConsumer>(1);

            firstChannel.Setup(m => m.BasicConsume(It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<IBasicConsumer>())).Callback<string, bool, IBasicConsumer>(
                (a1, a2, a3) => consumer.Add(a3));

            var commitLatch = new CountdownEvent(1);
            firstChannel.Setup(m => m.TxCommit()).Callback(() => commitLatch.Signal());

            var latch = new CountdownEvent(1);
            var exposed = new AtomicReference<IModel>();
            var container = new SimpleMessageListenerContainer(singleConnectionFactory);
            var mockListener = new Mock<IChannelAwareMessageListener>();
            mockListener.Setup(m => m.OnMessage(It.IsAny<Message>(), It.IsAny<IModel>())).Callback<Message, IModel>(
                (message, channel) =>
                {
                    exposed.LazySet(channel);
                    var rabbitTemplate = new RabbitTemplate(singleConnectionFactory);
                    rabbitTemplate.ChannelTransacted = true;

                    // should use same channel as container
                    rabbitTemplate.ConvertAndSend("foo", "bar", "baz");
                    latch.Signal();
                });
            container.MessageListener = mockListener.Object;

            container.QueueNames = new[] { "queue" };
            container.ChannelTransacted = true;
            container.ExposeListenerChannel = false;
            container.ShutdownTimeout = 100;
            container.AfterPropertiesSet();
            container.Start();

            IBasicConsumer currentConsumer;
            consumer.TryTake(out currentConsumer, timeout);
            Assert.IsNotNull(currentConsumer, "Timed out getting consumer.");
            currentConsumer.HandleBasicDeliver("qux", 1, false, "foo", "bar", new BasicProperties(), new byte[] { 0 });

            Assert.IsTrue(latch.Wait(new TimeSpan(0, 0, 10)));

            var e = tooManyChannels.Count;
            if (e > 0)
            {
                throw tooManyChannels.Take();
            }

            // once for listener, once for exposed + 0 for template (used bound)
            mockConnection.Verify(m => m.CreateModel(), Times.Exactly(2));
            Assert.IsTrue(commitLatch.Wait(new TimeSpan(0, 0, 10)));
            firstChannel.Verify(m => m.TxCommit(), Times.Once());
            secondChannel.Verify(m => m.TxCommit(), Times.Once());
            secondChannel.Verify(m => m.BasicPublish(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<IBasicProperties>(), It.IsAny<byte[]>()), Times.Once());

            Assert.AreSame(secondChannel.Object, exposed.Value);

            firstChannel.Verify(m => m.Close(), Times.Never());
            secondChannel.Verify(m => m.Close(), Times.Once());
            container.Stop();
        }
        /// <summary>
        /// Does the sunny day test.
        /// </summary>
        /// <param name="latch">The latch.</param>
        /// <param name="listener">The listener.</param>
        /// <remarks></remarks>
        private void DoSunnyDayTest(CountDownLatch latch, object listener)
        {
            this.container = this.CreateContainer(listener);
            for (var i = 0; i < this.messageCount; i++)
            {
                this.template.ConvertAndSend(this.queue.Name, i + "foo");
            }

            var waited = latch.Await(new TimeSpan(0, 0, 0, Math.Max(2, this.messageCount / 40)));
            Assert.True(waited, "Timed out waiting for message");
            Assert.Null(this.template.ReceiveAndConvert(this.queue.Name));
        }
        public void TestListenerRecoversFromClosedChannelAndStop()
        {
            var template = new RabbitTemplate(this.CreateConnectionFactory());

            var latch = new CountdownEvent(this.messageCount);
            this.container = this.CreateContainer(queue.Name, new AbortChannelListener(latch), this.CreateConnectionFactory());

            var n = 0;
            while (n++ < 100 && this.container.ActiveConsumerCount != this.concurrentConsumers)
            {
                Thread.Sleep(50);
            }

            Assert.AreEqual(this.concurrentConsumers, this.container.ActiveConsumerCount);

            for (var i = 0; i < this.messageCount; i++)
            {
                template.ConvertAndSend(queue.Name, i + "foo");
            }

            var timeout = this.GetTimeout();
            Logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
            var waited = latch.Wait(new TimeSpan(0, 0, timeout));
            Assert.True(waited, "Timed out waiting for message");

            Assert.Null(template.ReceiveAndConvert(queue.Name));

            Assert.AreEqual(this.concurrentConsumers, this.container.ActiveConsumerCount);
            this.container.Stop();
            Assert.AreEqual(0, this.container.ActiveConsumerCount);
        }
        public void TestListenerRecoversFromClosedConnection()
        {
            var template = new RabbitTemplate(this.CreateConnectionFactory());

            var latch = new CountdownEvent(this.messageCount);
            var connectionFactory = this.CreateConnectionFactory();
            this.container = this.CreateContainer(queue.Name, new CloseConnectionListener((IConnectionProxy)connectionFactory.CreateConnection(), latch), connectionFactory);
            for (var i = 0; i < this.messageCount; i++)
            {
                template.ConvertAndSend(queue.Name, i + "foo");
            }

            var timeout = Math.Min(4 + (this.messageCount / (4 * this.concurrentConsumers)), 30);
            Logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
            var waited = latch.Wait(new TimeSpan(0, 0, timeout));
            Assert.True(waited, "Timed out waiting for message");

            Assert.Null(template.ReceiveAndConvert(queue.Name));
        }
 public void TestListenerTransactionalSunnyDay()
 {
     transactional = true;
     CountDownLatch latch = new CountDownLatch(messageCount);
     container = CreateContainer(new TxTestListener(latch, false, this));
     for (int i = 0; i < messageCount; i++)
     {
         template.ConvertAndSend(queue.Name, i + "foo");
     }
     int timeout = Math.Min(1 + messageCount / (4 * concurrentConsumers), 30);
     logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
     var waited = latch.Await(new TimeSpan(0, 0, 0, timeout));
     Assert.True(waited, "Timed out waiting for message");
     Assert.Null(template.ReceiveAndConvert(queue.Name));
 }
 public void TestListenerDoesNotRecoverFromMissingQueue()
 {
     try
     {
         this.concurrentConsumers = 3;
         var latch = new CountdownEvent(this.messageCount);
         this.container = this.CreateContainer("nonexistent", new VanillaListener(latch), this.CreateConnectionFactory());
     }
     catch (Exception e)
     {
         Assert.True(e is AmqpIllegalStateException);
         this.concurrentConsumers = 1;
     }
 }
        public void TestListenerRecoversFromDeadBroker()
        {
            var queues = this.brokerAdmin.GetQueues();
            Logger.Info("Queues: " + queues);
            Assert.AreEqual(1, queues.Count);
            Assert.True(queues[0].Durable);

            var template = new RabbitTemplate(this.connectionFactory);

            var latch = new CountdownEvent(this.messageCount);
            Assert.AreEqual(this.messageCount, latch.CurrentCount, "No more messages to receive before even sent!");
            this.container = this.CreateContainer(this.queue.Name, new VanillaListener(latch), this.connectionFactory);
            for (var i = 0; i < this.messageCount; i++)
            {
                template.ConvertAndSend(this.queue.Name, i + "foo");
            }

            Assert.True(latch.CurrentCount > 0, "No more messages to receive before broker stopped");
            Logger.Info(string.Format("Latch.CurrentCount Before Shutdown: {0}", latch.CurrentCount));
            this.brokerAdmin.StopBrokerApplication();
            Assert.True(latch.CurrentCount > 0, "No more messages to receive after broker stopped");
            Logger.Info(string.Format("Latch.CurrentCount After Shutdown: {0}", latch.CurrentCount));
            var waited = latch.Wait(500);
            Assert.False(waited, "Did not time out waiting for message");

            this.container.Stop();
            Assert.AreEqual(0, this.container.ActiveConsumerCount);
            Logger.Info(string.Format("Latch.CurrentCount After Container Stop: {0}", latch.CurrentCount));
            this.brokerAdmin.StartBrokerApplication();
            queues = this.brokerAdmin.GetQueues();
            Logger.Info("Queues: " + queues);
            this.container.Start();
            Logger.Info(string.Format("Concurrent Consumers After Container Start: {0}", this.container.ActiveConsumerCount));
            Assert.AreEqual(this.concurrentConsumers, this.container.ActiveConsumerCount);
            Logger.Info(string.Format("Latch.CurrentCount After Container Start: {0}", latch.CurrentCount));
            var timeout = Math.Min((4 + this.messageCount) / (4 * this.concurrentConsumers), 30);
            Logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
            waited = latch.Wait(timeout * 1000);
            Assert.True(waited, "Timed out waiting for message");

            Assert.IsNull(template.ReceiveAndConvert(this.queue.Name));
        }
 /// <summary>Initializes a new instance of the <see cref="AsyncMessageProcessingConsumer"/> class.</summary>
 /// <param name="consumer">The consumer.</param>
 /// <param name="outer">The outer.</param>
 public AsyncMessageProcessingConsumer(BlockingQueueConsumer consumer, SimpleMessageListenerContainer outer)
 {
     this.consumer = consumer;
     this.outer    = outer;
     this.start    = new CountdownEvent(1);
 }
        private void DoTestRetry(int messageCount, int txSize, int failFrequency, int concurrentConsumers, bool stateful)
        {
            var failedMessageCount = messageCount / failFrequency + (messageCount % failFrequency == 0 ? 0 : 1);

            template = CreateTemplate(concurrentConsumers);
            for (var i = 0; i < messageCount; i++)
            {
                template.ConvertAndSend(queue.Name, i.ToString());
            }

            var container = new SimpleMessageListenerContainer(template.ConnectionFactory);
            var listener = new RetryPocoListener(failFrequency);
            container.MessageListener = new MessageListenerAdapter(listener);
            container.AcknowledgeMode = AcknowledgeModeUtils.AcknowledgeMode.AUTO;
            container.IsChannelTransacted = true;
            container.TxSize = txSize;
            container.ConcurrentConsumers = concurrentConsumers;

            var latch = new CountdownEvent(failedMessageCount);
            //container.AdviceChain = new IAdvice[] { CreateRetryInterceptor(latch, stateful) };

            container.QueueNames = new string[] { queue.Name };
            container.AfterPropertiesSet();
            container.Start();

            try
            {
                var timeout = Math.Min(1 + messageCount / concurrentConsumers, 30);

                var count = messageCount;
                logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
                Task.Factory.StartNew(() =>
                                          {
                                              while (container.ActiveConsumerCount > 0)
                                              {
                                                  try
                                                  {
                                                      Thread.Sleep(100);
                                                  }
                                                  catch (ThreadInterruptedException e)
                                                  {
                                                      latch.Signal();
                                                      Thread.CurrentThread.Interrupt();
                                                      return;
                                                  }
                                              }
                                              for (var i = 0; i < count; i++)
                                              {
                                                  latch.Signal();
                                              }
                                          });
                var waited = latch.Wait(timeout * 1000);
                logger.Info("All messages recovered: " + waited);
                Assert.AreEqual(concurrentConsumers, container.ActiveConsumerCount);
                Assert.True(waited, "Timed out waiting for messages");

                // Retried each failure 3 times (default retry policy)...
                Assert.AreEqual(3 * failedMessageCount, listener.Count);

                // All failed messages recovered
                Assert.AreEqual(null, this.template.ReceiveAndConvert(queue.Name));
            }
            finally
            {
                container.Shutdown();
                Assert.AreEqual(0, container.ActiveConsumerCount);
            }
        }
        public void TestChannelAwareMessageListener()
        {
            var mockConnectionFactory = new Mock<ConnectionFactory>();
            var mockConnection = new Mock<IConnection>();
            var onlyChannel = new Mock<IModel>();
            onlyChannel.Setup(m => m.IsOpen).Returns(true);
            onlyChannel.Setup(m => m.CreateBasicProperties()).Returns(() => new BasicProperties());

            var singleConnectionFactory = new SingleConnectionFactory(mockConnectionFactory.Object);

            mockConnectionFactory.Setup(m => m.CreateConnection()).Returns(mockConnection.Object);
            mockConnection.Setup(m => m.IsOpen).Returns(true);

            var tooManyChannels = new AtomicReference<Exception>();
            var done = false;
            mockConnection.Setup(m => m.CreateModel()).Returns(
                () =>
                {
                    if (!done)
                    {
                        done = true;
                        return onlyChannel.Object;
                    }

                    tooManyChannels.LazySet(new Exception("More than one channel requested"));
                    var internalChannel = new Mock<IModel>();
                    internalChannel.Setup(m => m.IsOpen).Returns(true);
                    return internalChannel.Object;
                });

            var consumer = new BlockingCollection<IBasicConsumer>(1);

            onlyChannel.Setup(m => m.BasicConsume(It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<IBasicConsumer>())).Callback<string, bool, IBasicConsumer>(
                (a1, a2, a3) => consumer.Add(a3));

            var commitLatch = new CountdownEvent(1);
            onlyChannel.Setup(m => m.TxCommit()).Callback(
                () =>
                {
                    if (commitLatch.CurrentCount > 0)
                    {
                        commitLatch.Signal();
                    }
                });

            var latch = new CountdownEvent(1);
            var exposed = new AtomicReference<IModel>();
            var container = new SimpleMessageListenerContainer(singleConnectionFactory);
            var mockListener = new Mock<IChannelAwareMessageListener>();
            mockListener.Setup(m => m.OnMessage(It.IsAny<Message>(), It.IsAny<IModel>())).Callback<Message, IModel>(
                (message, channel) =>
                {
                    exposed.LazySet(channel);
                    var rabbitTemplate = new RabbitTemplate(singleConnectionFactory);
                    rabbitTemplate.ChannelTransacted = true;

                    // should use same channel as container
                    rabbitTemplate.ConvertAndSend("foo", "bar", "baz");
                    if (latch.CurrentCount > 0)
                    {
                        latch.Signal();
                    }
                });
            container.MessageListener = mockListener.Object;
            container.QueueNames = new[] { "queue" };
            container.ChannelTransacted = true;
            container.ShutdownTimeout = 100;
            container.TransactionManager = DummyTxManager.Instance();
            container.AfterPropertiesSet();
            container.Start();

            IBasicConsumer currentConsumer;
            consumer.TryTake(out currentConsumer, this.timeout);
            Assert.IsNotNull(currentConsumer, "Timed out getting consumer.");
            currentConsumer.HandleBasicDeliver("qux", 1, false, "foo", "bar", new BasicProperties(), new byte[] { 0 });

            Assert.IsTrue(latch.Wait(new TimeSpan(0, 0, 10)));

            var e = tooManyChannels.Value;
            if (e != null)
            {
                throw e;
            }

            mockConnection.Verify(m => m.CreateModel(), Times.Once());
            Assert.IsTrue(commitLatch.Wait(new TimeSpan(0, 0, 10)));
            onlyChannel.Verify(m => m.TxCommit(), Times.Once());
            onlyChannel.Verify(m => m.BasicPublish(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<IBasicProperties>(), It.IsAny<byte[]>()), Times.Once());

            // verify close() was never called on the channel
            onlyChannel.Verify(m => m.Close(), Times.Never());

            container.Stop();
            container.Dispose();
            container = null;

            Assert.AreSame(onlyChannel.Object, exposed.Value);
        }
        public void Clear()
        {
            // Wait for broker communication to finish before trying to stop container
            Thread.Sleep(300);
            Logger.Debug("Shutting down at end of test");
            if (this.container != null)
            {
                this.container.Shutdown();
            }

            if (this.container != null)
            {
                this.container.Dispose();
            }

            this.container = null;
        }
        /// <summary>Does the test.</summary>
        /// <param name="level">The level.</param>
        /// <param name="concurrency">The concurrency.</param>
        /// <param name="transactionMode">The transaction mode.</param>
        private void DoTest(MessageCount level, Concurrency concurrency, TransactionModeUtils.TransactionMode transactionMode)
        {
            var messageCount = (int)level;
            var concurrentConsumers = (int)concurrency;
            var transactional = transactionMode.IsTransactional();

            var template = this.CreateTemplate(concurrentConsumers);

            var latch = new CountdownEvent(messageCount);
            for (var i = 0; i < messageCount; i++)
            {
                template.ConvertAndSend(queue.Name, i + "foo");
            }

            var container = new SimpleMessageListenerContainer(template.ConnectionFactory);
            var listener = new LifecyclePocoListener(latch);
            container.MessageListener = new MessageListenerAdapter(listener);
            container.AcknowledgeMode = transactionMode.AcknowledgeMode();
            container.ChannelTransacted = transactionMode.IsTransactional();
            container.ConcurrentConsumers = concurrentConsumers;

            if (transactionMode.Prefetch() > 0)
            {
                container.PrefetchCount = transactionMode.Prefetch();
                container.TxSize = transactionMode.TxSize();
            }

            container.QueueNames = new[] { queue.Name };
            container.AfterPropertiesSet();
            container.Start();

            try
            {
                var waited = latch.Wait(50);
                Logger.Info("All messages received before stop: " + waited);
                if (messageCount > 1)
                {
                    Assert.False(waited, "Expected not to receive all messages before stop");
                }

                Assert.AreEqual(concurrentConsumers, container.ActiveConsumerCount);
                container.Stop();
                Thread.Sleep(500);
                Assert.AreEqual(0, container.ActiveConsumerCount);
                if (!transactional)
                {
                    var messagesReceivedAfterStop = listener.Count;
                    waited = latch.Wait(500);
                    Logger.Info("All messages received after stop: " + waited);
                    if (messageCount < 100)
                    {
                        Assert.True(waited, "Expected to receive all messages after stop");
                    }

                    Assert.AreEqual(messagesReceivedAfterStop, listener.Count, "Unexpected additional messages received after stop");

                    for (var i = 0; i < messageCount; i++)
                    {
                        template.ConvertAndSend(queue.Name, i + "bar");
                    }

                    latch = new CountdownEvent(messageCount);
                    listener.Reset(latch);
                }

                var messagesReceivedBeforeStart = listener.Count;
                container.Start();
                var timeout = Math.Min(1 + messageCount / (4 * concurrentConsumers), 30);

                Logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
                waited = latch.Wait(timeout * 1000);
                Logger.Info("All messages received after start: " + waited);
                Assert.AreEqual(concurrentConsumers, container.ActiveConsumerCount);
                if (transactional)
                {
                    Assert.True(waited, "Timed out waiting for message");
                }
                else
                {
                    var count = listener.Count;
                    Assert.True(messagesReceivedBeforeStart < count, "Expected additional messages received after start: " + messagesReceivedBeforeStart + ">=" + count);
                    Assert.Null(template.Receive(queue.Name), "Messages still available");
                }

                Assert.AreEqual(concurrentConsumers, container.ActiveConsumerCount);
            }
            finally
            {
                // Wait for broker communication to finish before trying to stop
                // container
                Thread.Sleep(500);
                container.Shutdown();
                Assert.AreEqual(0, container.ActiveConsumerCount);
            }

            Assert.Null(template.ReceiveAndConvert(queue.Name));
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="AsyncMessageProcessingConsumer"/> class.
 /// </summary>
 /// <param name="consumer">
 /// The consumer.
 /// </param>
 /// <param name="outer">
 /// The outer.
 /// </param>
 public AsyncMessageProcessingConsumer(BlockingQueueConsumer consumer, SimpleMessageListenerContainer outer)
 {
     this.consumer = consumer;
     this.outer = outer;
     this.start = new CountDownLatch(1);
 }
 /// <summary>Creates the container.</summary>
 /// <param name="queueName">Name of the queue.</param>
 /// <param name="listener">The listener.</param>
 /// <param name="connectionFactory">The connection factory.</param>
 /// <returns>The container.</returns>
 private SimpleMessageListenerContainer CreateContainer(string queueName, object listener, IConnectionFactory connectionFactory)
 {
     var container = new SimpleMessageListenerContainer(connectionFactory);
     container.MessageListener = new MessageListenerAdapter(listener);
     container.QueueNames = new[] { queueName };
     container.TxSize = this.txSize;
     container.PrefetchCount = this.txSize;
     container.ConcurrentConsumers = this.concurrentConsumers;
     container.ChannelTransacted = this.transactional;
     container.AcknowledgeMode = this.acknowledgeMode;
     container.AfterPropertiesSet();
     container.Start();
     return container;
 }
        /// <summary>
        /// Does the test.
        /// </summary>
        /// <param name="concurrentConsumers">The concurrent consumers.</param>
        /// <param name="configurer">The configurer.</param>
        /// <remarks></remarks>
        private void DoTest(int concurrentConsumers, IContainerConfigurer configurer)
        {
            var messageCount = 10;
            var template = new RabbitTemplate();
            var connectionFactory = new CachingConnectionFactory();
            connectionFactory.ChannelCacheSize = concurrentConsumers;
            connectionFactory.Port = BrokerTestUtils.GetPort();
            template.ConnectionFactory = connectionFactory;
            var messageConverter = new SimpleMessageConverter();
            messageConverter.CreateMessageIds = true;
            template.MessageConverter = messageConverter;
            for (var i = 0; i < messageCount; i++)
            {
                template.ConvertAndSend(queue1.Name, i.ToString());
                template.ConvertAndSend(queue2.Name, i.ToString());
            }

            var container = new SimpleMessageListenerContainer(connectionFactory);
            var latch = new CountdownEvent(messageCount * 2);
            var listener = new MultiplePocoListener(latch);
            container.MessageListener = new MessageListenerAdapter(listener);
            container.AcknowledgeMode = AcknowledgeModeUtils.AcknowledgeMode.AUTO;
            container.IsChannelTransacted = true;
            container.ConcurrentConsumers = concurrentConsumers;
            configurer.Configure(container);
            container.AfterPropertiesSet();
            container.Start();
            try
            {
                var timeout = Math.Min((1 + messageCount) / concurrentConsumers, 30);
                var waited = latch.Wait(timeout * 1000);
                logger.Info("All messages recovered: " + waited);
                Assert.AreEqual(concurrentConsumers, container.ActiveConsumerCount);
                Assert.True(waited, "Timed out waiting for messages");
            }
            catch (ThreadInterruptedException e)
            {
                Thread.CurrentThread.Interrupt();
                throw new ThreadStateException("unexpected interruption");
            }
            finally
            {
                container.Shutdown();
                Assert.AreEqual(0, container.ActiveConsumerCount);
            }
            Assert.Null(template.ReceiveAndConvert(queue1.Name));
            Assert.Null(template.ReceiveAndConvert(queue2.Name));
        }