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); } }
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)); }