Channel channel = channelHolder.getChannel(); if (this.confirmsOrReturnsCapable) { addListener(channel);
/** * Get the channel holder associated with a direct reply-to consumer; contains a * consumer epoch to prevent inappropriate releases. * @return the channel holder. */ public ChannelHolder getChannelHolder() { synchronized (this.consumersMonitor) { ChannelHolder channelHolder = null; while (channelHolder == null) { if (!isRunning()) { throw new IllegalStateException("Direct reply-to container is not running"); } for (SimpleConsumer consumer : this.consumers) { Channel candidate = consumer.getChannel(); if (candidate.isOpen() && this.inUseConsumerChannels.putIfAbsent(candidate, consumer) == null) { channelHolder = new ChannelHolder(candidate, consumer.incrementAndGetEpoch()); this.whenUsed.put(consumer, System.currentTimeMillis()); break; } } if (channelHolder == null) { this.consumerCount++; super.setConsumersPerQueue(this.consumerCount); } } return channelHolder; } }
/** * Release the consumer associated with the channel for reuse. * Set cancelConsumer to true if the client is not prepared to handle/discard a * late arriving reply. * @param channelHolder the channel holder. * @param cancelConsumer true to cancel the consumer. * @param message a message to be included in the cancel event if cancelConsumer is true. */ public void releaseConsumerFor(ChannelHolder channelHolder, boolean cancelConsumer, @Nullable String message) { synchronized (this.consumersMonitor) { SimpleConsumer consumer = this.inUseConsumerChannels.get(channelHolder.getChannel()); if (consumer != null && consumer.getEpoch() == channelHolder.getConsumerEpoch()) { this.inUseConsumerChannels.remove(channelHolder.getChannel()); if (cancelConsumer) { Assert.isTrue(message != null, "A 'message' is required when 'cancelConsumer' is 'true'"); consumer.cancelConsumer("Consumer " + this + " canceled due to " + message); } } } }
ChannelHolder channel1 = container.getChannelHolder(); BasicProperties props = new BasicProperties().builder().replyTo(Address.AMQ_RABBITMQ_REPLY_TO).build(); channel1.getChannel().basicPublish("", TEST_RELEASE_CONSUMER_Q, props, "foo".getBytes()); Channel replyChannel = connectionFactory.createConnection().createChannel(false); GetResponse request = replyChannel.basicGet(TEST_RELEASE_CONSUMER_Q, true); assertSame(channel1.getChannel(), channel2.getChannel()); container.releaseConsumerFor(channel1, false, null); // simulate race for future timeout/cancel and onMessage() Map<?, ?> inUse = TestUtils.getPropertyValue(container, "inUseConsumerChannels", Map.class);
Channel channel = channelHolder.getChannel(); if (this.confirmsOrReturnsCapable) { addListener(channel);
@Test public void testReplyToConsumersReduced() throws Exception { CachingConnectionFactory cf = new CachingConnectionFactory("localhost"); DirectReplyToMessageListenerContainer container = new DirectReplyToMessageListenerContainer(cf); container.setBeanName("reducing"); container.setIdleEventInterval(100); CountDownLatch latch = new CountDownLatch(5); container.setApplicationEventPublisher(e -> { if (e instanceof ListenerContainerIdleEvent) { latch.countDown(); } }); container.afterPropertiesSet(); container.start(); ChannelHolder channelHolder1 = container.getChannelHolder(); ChannelHolder channelHolder2 = container.getChannelHolder(); assertTrue(activeConsumerCount(container, 2)); container.releaseConsumerFor(channelHolder2, false, null); assertTrue(latch.await(10, TimeUnit.SECONDS)); assertTrue(channelHolder1.getChannel().isOpen()); container.releaseConsumerFor(channelHolder1, false, null); assertTrue(activeConsumerCount(container, 0)); container.stop(); cf.destroy(); }
private <C> RabbitConverterFuture<C> convertSendAndReceive(String exchange, String routingKey, Object object, MessagePostProcessor messagePostProcessor, ParameterizedTypeReference<C> responseType) { AsyncCorrelationData<C> correlationData = new AsyncCorrelationData<C>(messagePostProcessor, responseType, this.enableConfirms); if (this.container != null) { this.template.convertAndSend(exchange, routingKey, object, this.messagePostProcessor, correlationData); } else { MessageConverter converter = this.template.getMessageConverter(); if (converter == null) { throw new AmqpIllegalStateException( "No 'messageConverter' specified. Check configuration of RabbitTemplate."); } Message message = converter.toMessage(object, new MessageProperties()); this.messagePostProcessor.postProcessMessage(message, correlationData); ChannelHolder channelHolder = this.directReplyToContainer.getChannelHolder(); correlationData.future.setChannelHolder(channelHolder); sendDirect(channelHolder.getChannel(), exchange, routingKey, message, correlationData); } RabbitConverterFuture<C> future = correlationData.future; future.startTimer(); return future; }
/** * Get the channel holder associated with a direct reply-to consumer; contains a * consumer epoch to prevent inappropriate releases. * @return the channel holder. */ public ChannelHolder getChannelHolder() { synchronized (this.consumersMonitor) { ChannelHolder channelHolder = null; while (channelHolder == null) { if (!isRunning()) { throw new IllegalStateException("Direct reply-to container is not running"); } for (SimpleConsumer consumer : this.consumers) { Channel candidate = consumer.getChannel(); if (candidate.isOpen() && this.inUseConsumerChannels.putIfAbsent(candidate, consumer) == null) { channelHolder = new ChannelHolder(candidate, consumer.incrementAndGetEpoch()); this.whenUsed.put(consumer, System.currentTimeMillis()); break; } } if (channelHolder == null) { this.consumerCount++; super.setConsumersPerQueue(this.consumerCount); } } return channelHolder; } }
@Override public RabbitMessageFuture sendAndReceive(String exchange, String routingKey, Message message) { String correlationId = getOrSetCorrelationIdAndSetReplyTo(message); RabbitMessageFuture future = new RabbitMessageFuture(correlationId, message); CorrelationData correlationData = null; if (this.enableConfirms) { correlationData = new CorrelationData(correlationId); future.setConfirm(new SettableListenableFuture<>()); } this.pending.put(correlationId, future); if (this.container != null) { this.template.send(exchange, routingKey, message, correlationData); } else { ChannelHolder channelHolder = this.directReplyToContainer.getChannelHolder(); future.setChannelHolder(channelHolder); sendDirect(channelHolder.getChannel(), exchange, routingKey, message, correlationData); } future.startTimer(); return future; }
@Override public RabbitMessageFuture sendAndReceive(String exchange, String routingKey, Message message) { String correlationId = getOrSetCorrelationIdAndSetReplyTo(message); RabbitMessageFuture future = new RabbitMessageFuture(correlationId, message); CorrelationData correlationData = null; if (this.enableConfirms) { correlationData = new CorrelationData(correlationId); future.setConfirm(new SettableListenableFuture<>()); } this.pending.put(correlationId, future); if (this.container != null) { this.template.send(exchange, routingKey, message, correlationData); } else { ChannelHolder channelHolder = this.directReplyToContainer.getChannelHolder(); future.setChannelHolder(channelHolder); sendDirect(channelHolder.getChannel(), exchange, routingKey, message, correlationData); } future.startTimer(); return future; }
private <C> RabbitConverterFuture<C> convertSendAndReceive(String exchange, String routingKey, Object object, MessagePostProcessor messagePostProcessor, ParameterizedTypeReference<C> responseType) { AsyncCorrelationData<C> correlationData = new AsyncCorrelationData<C>(messagePostProcessor, responseType, this.enableConfirms); if (this.container != null) { this.template.convertAndSend(exchange, routingKey, object, this.messagePostProcessor, correlationData); } else { MessageConverter converter = this.template.getMessageConverter(); if (converter == null) { throw new AmqpIllegalStateException( "No 'messageConverter' specified. Check configuration of RabbitTemplate."); } Message message = converter.toMessage(object, new MessageProperties()); this.messagePostProcessor.postProcessMessage(message, correlationData); ChannelHolder channelHolder = this.directReplyToContainer.getChannelHolder(); correlationData.future.setChannelHolder(channelHolder); sendDirect(channelHolder.getChannel(), exchange, routingKey, message, correlationData); } RabbitConverterFuture<C> future = correlationData.future; future.startTimer(); return future; }
/** * Release the consumer associated with the channel for reuse. * Set cancelConsumer to true if the client is not prepared to handle/discard a * late arriving reply. * @param channelHolder the channel holder. * @param cancelConsumer true to cancel the consumer. * @param message a message to be included in the cancel event if cancelConsumer is true. */ public void releaseConsumerFor(ChannelHolder channelHolder, boolean cancelConsumer, @Nullable String message) { synchronized (this.consumersMonitor) { SimpleConsumer consumer = this.inUseConsumerChannels.get(channelHolder.getChannel()); if (consumer != null && consumer.getEpoch() == channelHolder.getConsumerEpoch()) { this.inUseConsumerChannels.remove(channelHolder.getChannel()); if (cancelConsumer) { Assert.isTrue(message != null, "A 'message' is required when 'cancelConsumer' is 'true'"); consumer.cancelConsumer("Consumer " + this + " canceled due to " + message); } } } }