Configure virtual threads on the RabbitMQ listener
Closes gh-36387
This commit is contained in:
parent
f85a7258a6
commit
b1a3dad16c
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.boot.autoconfigure.amqp;
|
package org.springframework.boot.autoconfigure.amqp;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import org.springframework.amqp.rabbit.config.AbstractRabbitListenerContainerFactory;
|
import org.springframework.amqp.rabbit.config.AbstractRabbitListenerContainerFactory;
|
||||||
import org.springframework.amqp.rabbit.config.RetryInterceptorBuilder;
|
import org.springframework.amqp.rabbit.config.RetryInterceptorBuilder;
|
||||||
|
@ -47,6 +48,8 @@ public abstract class AbstractRabbitListenerContainerFactoryConfigurer<T extends
|
||||||
|
|
||||||
private final RabbitProperties rabbitProperties;
|
private final RabbitProperties rabbitProperties;
|
||||||
|
|
||||||
|
private Executor taskExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new configurer that will use the given {@code rabbitProperties}.
|
* Creates a new configurer that will use the given {@code rabbitProperties}.
|
||||||
* @param rabbitProperties properties to use
|
* @param rabbitProperties properties to use
|
||||||
|
@ -81,6 +84,14 @@ public abstract class AbstractRabbitListenerContainerFactoryConfigurer<T extends
|
||||||
this.retryTemplateCustomizers = retryTemplateCustomizers;
|
this.retryTemplateCustomizers = retryTemplateCustomizers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the task executor to use.
|
||||||
|
* @param taskExecutor the task executor
|
||||||
|
*/
|
||||||
|
public void setTaskExecutor(Executor taskExecutor) {
|
||||||
|
this.taskExecutor = taskExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
protected final RabbitProperties getRabbitProperties() {
|
protected final RabbitProperties getRabbitProperties() {
|
||||||
return this.rabbitProperties;
|
return this.rabbitProperties;
|
||||||
}
|
}
|
||||||
|
@ -119,6 +130,9 @@ public abstract class AbstractRabbitListenerContainerFactoryConfigurer<T extends
|
||||||
factory.setMissingQueuesFatal(configuration.isMissingQueuesFatal());
|
factory.setMissingQueuesFatal(configuration.isMissingQueuesFatal());
|
||||||
factory.setDeBatchingEnabled(configuration.isDeBatchingEnabled());
|
factory.setDeBatchingEnabled(configuration.isDeBatchingEnabled());
|
||||||
factory.setForceStop(configuration.isForceStop());
|
factory.setForceStop(configuration.isForceStop());
|
||||||
|
if (this.taskExecutor != null) {
|
||||||
|
factory.setTaskExecutor(this.taskExecutor);
|
||||||
|
}
|
||||||
ListenerRetry retryConfig = configuration.getRetry();
|
ListenerRetry retryConfig = configuration.getRetry();
|
||||||
if (retryConfig.isEnabled()) {
|
if (retryConfig.isEnabled()) {
|
||||||
RetryInterceptorBuilder<?, ?> builder = (retryConfig.isStateless()) ? RetryInterceptorBuilder.stateless()
|
RetryInterceptorBuilder<?, ?> builder = (retryConfig.isStateless()) ? RetryInterceptorBuilder.stateless()
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.autoconfigure.thread.VirtualThreads;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@ -51,13 +52,17 @@ class RabbitAnnotationDrivenConfiguration {
|
||||||
|
|
||||||
private final RabbitProperties properties;
|
private final RabbitProperties properties;
|
||||||
|
|
||||||
|
private final ObjectProvider<VirtualThreads> virtualThreads;
|
||||||
|
|
||||||
RabbitAnnotationDrivenConfiguration(ObjectProvider<MessageConverter> messageConverter,
|
RabbitAnnotationDrivenConfiguration(ObjectProvider<MessageConverter> messageConverter,
|
||||||
ObjectProvider<MessageRecoverer> messageRecoverer,
|
ObjectProvider<MessageRecoverer> messageRecoverer,
|
||||||
ObjectProvider<RabbitRetryTemplateCustomizer> retryTemplateCustomizers, RabbitProperties properties) {
|
ObjectProvider<RabbitRetryTemplateCustomizer> retryTemplateCustomizers, RabbitProperties properties,
|
||||||
|
ObjectProvider<VirtualThreads> virtualThreads) {
|
||||||
this.messageConverter = messageConverter;
|
this.messageConverter = messageConverter;
|
||||||
this.messageRecoverer = messageRecoverer;
|
this.messageRecoverer = messageRecoverer;
|
||||||
this.retryTemplateCustomizers = retryTemplateCustomizers;
|
this.retryTemplateCustomizers = retryTemplateCustomizers;
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
|
this.virtualThreads = virtualThreads;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -68,6 +73,7 @@ class RabbitAnnotationDrivenConfiguration {
|
||||||
configurer.setMessageConverter(this.messageConverter.getIfUnique());
|
configurer.setMessageConverter(this.messageConverter.getIfUnique());
|
||||||
configurer.setMessageRecoverer(this.messageRecoverer.getIfUnique());
|
configurer.setMessageRecoverer(this.messageRecoverer.getIfUnique());
|
||||||
configurer.setRetryTemplateCustomizers(this.retryTemplateCustomizers.orderedStream().toList());
|
configurer.setRetryTemplateCustomizers(this.retryTemplateCustomizers.orderedStream().toList());
|
||||||
|
this.virtualThreads.ifAvailable((virtualThreads) -> configurer.setTaskExecutor(virtualThreads.getExecutor()));
|
||||||
return configurer;
|
return configurer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +98,7 @@ class RabbitAnnotationDrivenConfiguration {
|
||||||
configurer.setMessageConverter(this.messageConverter.getIfUnique());
|
configurer.setMessageConverter(this.messageConverter.getIfUnique());
|
||||||
configurer.setMessageRecoverer(this.messageRecoverer.getIfUnique());
|
configurer.setMessageRecoverer(this.messageRecoverer.getIfUnique());
|
||||||
configurer.setRetryTemplateCustomizers(this.retryTemplateCustomizers.orderedStream().toList());
|
configurer.setRetryTemplateCustomizers(this.retryTemplateCustomizers.orderedStream().toList());
|
||||||
|
this.virtualThreads.ifAvailable((virtualThreads) -> configurer.setTaskExecutor(virtualThreads.getExecutor()));
|
||||||
return configurer;
|
return configurer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ import com.rabbitmq.client.impl.CredentialsRefreshService;
|
||||||
import com.rabbitmq.client.impl.DefaultCredentialsProvider;
|
import com.rabbitmq.client.impl.DefaultCredentialsProvider;
|
||||||
import org.aopalliance.aop.Advice;
|
import org.aopalliance.aop.Advice;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.condition.EnabledForJreRange;
|
||||||
|
import org.junit.jupiter.api.condition.JRE;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
|
|
||||||
|
@ -58,6 +60,7 @@ import org.springframework.amqp.rabbit.retry.MessageRecoverer;
|
||||||
import org.springframework.amqp.support.converter.MessageConverter;
|
import org.springframework.amqp.support.converter.MessageConverter;
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
|
import org.springframework.boot.autoconfigure.thread.VirtualThreadsAutoConfiguration;
|
||||||
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
import org.springframework.boot.test.system.CapturedOutput;
|
import org.springframework.boot.test.system.CapturedOutput;
|
||||||
|
@ -532,6 +535,19 @@ class RabbitAutoConfigurationTests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnabledForJreRange(min = JRE.JAVA_21)
|
||||||
|
void shouldConfigureVirtualThreads() {
|
||||||
|
this.contextRunner.withConfiguration(AutoConfigurations.of(VirtualThreadsAutoConfiguration.class))
|
||||||
|
.withPropertyValues("spring.threads.virtual.enabled=true")
|
||||||
|
.run((context) -> {
|
||||||
|
SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory = context
|
||||||
|
.getBean("rabbitListenerContainerFactory", SimpleRabbitListenerContainerFactory.class);
|
||||||
|
Object executor = ReflectionTestUtils.getField(rabbitListenerContainerFactory, "taskExecutor");
|
||||||
|
assertThat(executor).as("rabbitListenerContainerFactory.taskExecutor").isNotNull();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSimpleRabbitListenerContainerFactoryWithDefaultForceStop() {
|
void testSimpleRabbitListenerContainerFactoryWithDefaultForceStop() {
|
||||||
this.contextRunner
|
this.contextRunner
|
||||||
|
|
Loading…
Reference in New Issue