@Before public void declareQueue() { CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setChannelCacheSize(concurrentConsumers); // connectionFactory.setPort(5673); template.setConnectionFactory(connectionFactory); }
@Before public void createConnectionFactory() { CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setChannelCacheSize(concurrentConsumers); connectionFactory.setPort(BrokerTestUtils.getPort()); template.setConnectionFactory(connectionFactory); }
@Before public void declareQueue() { CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setHost("localhost"); connectionFactory.setChannelCacheSize(concurrentConsumers); connectionFactory.setPort(BrokerTestUtils.getPort()); template.setConnectionFactory(connectionFactory); }
@Before public void create() { connectionFactory = new CachingConnectionFactory(); connectionFactory.setHost("localhost"); connectionFactory.setChannelCacheSize(10); connectionFactory.setPort(BrokerTestUtils.getPort()); connectionFactoryWithConfirmsEnabled = new CachingConnectionFactory(); connectionFactoryWithConfirmsEnabled.setHost("localhost"); // When using publisher confirms, the cache size needs to be large enough // otherwise channels can be closed before confirms are received. connectionFactoryWithConfirmsEnabled.setChannelCacheSize(100); connectionFactoryWithConfirmsEnabled.setPort(BrokerTestUtils.getPort()); connectionFactoryWithConfirmsEnabled.setPublisherConfirms(true); templateWithConfirmsEnabled = new RabbitTemplate(connectionFactoryWithConfirmsEnabled); connectionFactoryWithReturnsEnabled = new CachingConnectionFactory(); connectionFactoryWithReturnsEnabled.setHost("localhost"); connectionFactoryWithReturnsEnabled.setChannelCacheSize(1); connectionFactoryWithReturnsEnabled.setPort(BrokerTestUtils.getPort()); connectionFactoryWithReturnsEnabled.setPublisherReturns(true); templateWithReturnsEnabled = new RabbitTemplate(connectionFactoryWithReturnsEnabled); }
private RabbitTemplate createTemplate(int concurrentConsumers) { RabbitTemplate template = new RabbitTemplate(); CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setHost("localhost"); connectionFactory.setChannelCacheSize(concurrentConsumers); connectionFactory.setPort(BrokerTestUtils.getPort()); template.setConnectionFactory(connectionFactory); if (messageConverter == null) { SimpleMessageConverter messageConverter = new SimpleMessageConverter(); messageConverter.setCreateMessageIds(true); this.messageConverter = messageConverter; } template.setMessageConverter(messageConverter); return template; }
private void doTest(int concurrentConsumers, ContainerConfigurer configurer) { int messageCount = 10; RabbitTemplate template = new RabbitTemplate(); CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setHost("localhost"); connectionFactory.setChannelCacheSize(concurrentConsumers); connectionFactory.setPort(BrokerTestUtils.getPort()); template.setConnectionFactory(connectionFactory); SimpleMessageConverter messageConverter = new SimpleMessageConverter(); messageConverter.setCreateMessageIds(true); template.setMessageConverter(messageConverter); for (int i = 0; i < messageCount; i++) { template.convertAndSend(queue1.getName(), new Integer(i)); template.convertAndSend(queue2.getName(), new Integer(i)); } final SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); final CountDownLatch latch = new CountDownLatch(messageCount * 2); PojoListener listener = new PojoListener(latch); container.setMessageListener(new MessageListenerAdapter(listener)); container.setAcknowledgeMode(AcknowledgeMode.AUTO); container.setChannelTransacted(true); container.setConcurrentConsumers(concurrentConsumers); configurer.configure(container); container.afterPropertiesSet(); container.start(); try { int timeout = Math.min(1 + messageCount / concurrentConsumers, 30); boolean waited = latch.await(timeout, TimeUnit.SECONDS); logger.info("All messages recovered: " + waited); assertEquals(concurrentConsumers, container.getActiveConsumerCount()); assertTrue("Timed out waiting for messages", waited); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IllegalStateException("unexpected interruption"); } finally { container.shutdown(); assertEquals(0, container.getActiveConsumerCount()); } assertNull(template.receiveAndConvert(queue1.getName())); assertNull(template.receiveAndConvert(queue2.getName())); connectionFactory.destroy(); }
/** * Avoid the possibility of not configuring the CachingConnectionFactory in sync with the number * of concurrent consumers. */ @Override protected void validateConfiguration() { super.validateConfiguration(); Assert.state( !(getAcknowledgeMode().isAutoAck() && transactionManager != null), "The acknowledgeMode is NONE (autoack in Rabbit terms) which is not consistent with having an " + "external transaction manager. Either use a different AcknowledgeMode or make sure the transactionManager is null."); if (this.getConnectionFactory() instanceof CachingConnectionFactory) { CachingConnectionFactory cf = (CachingConnectionFactory) getConnectionFactory(); if (cf.getChannelCacheSize() < this.concurrentConsumers) { cf.setChannelCacheSize(this.concurrentConsumers); logger.warn( "CachingConnectionFactory's channelCacheSize can not be less than the number of concurrentConsumers so it was reset to match: " + this.concurrentConsumers); } } }
/** * AMQP-262 Sets up a situation where we are processing 'multi' acks at the same time as adding a * new pending ack to the map. Test verifies we don't get a {@link * ConcurrentModificationException}. */ @SuppressWarnings({"rawtypes", "unchecked", "deprecation"}) @Test public void testConcurrentConfirms() throws Exception { ConnectionFactory mockConnectionFactory = mock(ConnectionFactory.class); Connection mockConnection = mock(Connection.class); Channel mockChannel = mock(Channel.class); when(mockChannel.getNextPublishSeqNo()).thenReturn(1L, 2L, 3L, 4L); when(mockConnectionFactory.newConnection((ExecutorService) null)).thenReturn(mockConnection); when(mockConnection.isOpen()).thenReturn(true); final PublisherCallbackChannelImpl channel = new PublisherCallbackChannelImpl(mockChannel); when(mockConnection.createChannel()).thenReturn(channel); CachingConnectionFactory ccf = new CachingConnectionFactory(mockConnectionFactory); ccf.setPublisherConfirms(true); ccf.setChannelCacheSize(3); final RabbitTemplate template = new RabbitTemplate(ccf); final CountDownLatch first2SentOnThread1Latch = new CountDownLatch(1); final CountDownLatch delayAckProcessingLatch = new CountDownLatch(1); final CountDownLatch startedProcessingMultiAcksLatch = new CountDownLatch(1); final CountDownLatch waitForAll3AcksLatch = new CountDownLatch(3); final CountDownLatch allSentLatch = new CountDownLatch(1); final AtomicInteger acks = new AtomicInteger(); template.setConfirmCallback( new ConfirmCallback() { @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { try { startedProcessingMultiAcksLatch.countDown(); // delay processing here; ensures thread 2 put would be concurrent delayAckProcessingLatch.await(2, TimeUnit.SECONDS); // only delay first time through delayAckProcessingLatch.countDown(); waitForAll3AcksLatch.countDown(); acks.incrementAndGet(); } catch (InterruptedException e) { e.printStackTrace(); } } }); Executors.newSingleThreadExecutor() .execute( new Runnable() { @Override public void run() { template.convertAndSend(ROUTE, (Object) "message", new CorrelationData("abc")); template.convertAndSend(ROUTE, (Object) "message", new CorrelationData("def")); first2SentOnThread1Latch.countDown(); } }); Executors.newSingleThreadExecutor() .execute( new Runnable() { @Override public void run() { try { startedProcessingMultiAcksLatch.await(); template.convertAndSend(ROUTE, (Object) "message", new CorrelationData("ghi")); allSentLatch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }); assertTrue(first2SentOnThread1Latch.await(10, TimeUnit.SECONDS)); // there should be no concurrent execution exception here channel.handleAck(2, true); assertTrue(allSentLatch.await(10, TimeUnit.SECONDS)); channel.handleAck(3, false); assertTrue(waitForAll3AcksLatch.await(10, TimeUnit.SECONDS)); assertEquals(3, acks.get()); // 3.3.1 client channel.basicConsume("foo", false, (Map) null, null); verify(mockChannel).basicConsume("foo", false, (Map) null, null); channel.basicQos(3, false); verify(mockChannel).basicQos(3, false); doReturn(true).when(mockChannel).flowBlocked(); assertTrue(channel.flowBlocked()); try { channel.flow(true); fail("Expected exception"); } catch (UnsupportedOperationException e) { } try { channel.getFlow(); fail("Expected exception"); } catch (UnsupportedOperationException e) { } // 3.2.4 client /* try { channel.basicConsume("foo", false, (Map) null, (Consumer) null); fail("Expected exception"); } catch (UnsupportedOperationException e) {} try { channel.basicQos(3, false); fail("Expected exception"); } catch (UnsupportedOperationException e) {} try { channel.flowBlocked(); fail("Expected exception"); } catch (UnsupportedOperationException e) {} channel.flow(true); verify(mockChannel).flow(true); channel.getFlow(); verify(mockChannel).getFlow(); */ }
@Test public void testPublisherConfirmNotReceivedMultiThreads() throws Exception { ConnectionFactory mockConnectionFactory = mock(ConnectionFactory.class); Connection mockConnection = mock(Connection.class); Channel mockChannel1 = mock(Channel.class); Channel mockChannel2 = mock(Channel.class); when(mockChannel1.isOpen()).thenReturn(true); when(mockChannel2.isOpen()).thenReturn(true); when(mockChannel1.getNextPublishSeqNo()).thenReturn(1L, 2L, 3L, 4L); when(mockChannel2.getNextPublishSeqNo()).thenReturn(1L, 2L, 3L, 4L); when(mockConnectionFactory.newConnection((ExecutorService) null)).thenReturn(mockConnection); when(mockConnection.isOpen()).thenReturn(true); PublisherCallbackChannelImpl channel1 = new PublisherCallbackChannelImpl(mockChannel1); PublisherCallbackChannelImpl channel2 = new PublisherCallbackChannelImpl(mockChannel2); when(mockConnection.createChannel()).thenReturn(channel1).thenReturn(channel2); CachingConnectionFactory ccf = new CachingConnectionFactory(mockConnectionFactory); ccf.setPublisherConfirms(true); ccf.setChannelCacheSize(3); final RabbitTemplate template = new RabbitTemplate(ccf); final AtomicBoolean confirmed = new AtomicBoolean(); template.setConfirmCallback( new ConfirmCallback() { @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { confirmed.set(true); } }); // Hold up the first thread so we get two channels final CountDownLatch threadLatch = new CountDownLatch(1); final CountDownLatch threadSentLatch = new CountDownLatch(1); // Thread 1 ExecutorService exec = Executors.newSingleThreadExecutor(); exec.execute( new Runnable() { @Override public void run() { template.execute( new ChannelCallback<Object>() { @Override public Object doInRabbit(Channel channel) throws Exception { try { threadLatch.await(10, TimeUnit.SECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } template.doSend( channel, "", ROUTE, new SimpleMessageConverter().toMessage("message", new MessageProperties()), false, new CorrelationData("def")); threadSentLatch.countDown(); return null; } }); } }); // Thread 2 template.convertAndSend(ROUTE, (Object) "message", new CorrelationData("abc")); // channel y threadLatch.countDown(); assertTrue(threadSentLatch.await(5, TimeUnit.SECONDS)); Collection<CorrelationData> unconfirmed = template.getUnconfirmed(-1); assertEquals(2, unconfirmed.size()); Set<String> ids = new HashSet<String>(); Iterator<CorrelationData> iterator = unconfirmed.iterator(); ids.add(iterator.next().getId()); ids.add(iterator.next().getId()); assertTrue(ids.remove("abc")); assertTrue(ids.remove("def")); assertFalse(confirmed.get()); DirectFieldAccessor dfa = new DirectFieldAccessor(template); Map<?, ?> pendingConfirms = (Map<?, ?>) dfa.getPropertyValue("pendingConfirms"); assertThat(pendingConfirms.size(), greaterThan(0)); // might use 2 or only 1 channel exec.shutdown(); assertTrue(exec.awaitTermination(10, TimeUnit.SECONDS)); ccf.destroy(); assertEquals(0, pendingConfirms.size()); }