diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.java index 6cc58a468daf..536dca4d7b52 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.java @@ -138,6 +138,9 @@ private ClientOptions.Builder initializeClientOptionsBuilder() { if (refreshProperties.isAdaptive()) { refreshBuilder.enableAllAdaptiveRefreshTriggers(); } + if (refreshProperties.isDynamicSources() != null) { + refreshBuilder.dynamicRefreshSources(refreshProperties.isDynamicSources()); + } return builder.topologyRefreshOptions(refreshBuilder.build()); } return ClientOptions.builder(); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisProperties.java index 803f60065db8..45ab80e00057 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisProperties.java @@ -410,6 +410,13 @@ public static class Refresh { */ private boolean adaptive; + /** + * Whether discovered nodes should be used as the source for the cluster + * topology. When set to false, only the initial seed nodes + * will be used as sources for topology discovery. + */ + private Boolean dynamicSources; + public Duration getPeriod() { return this.period; } @@ -426,6 +433,14 @@ public void setAdaptive(boolean adaptive) { this.adaptive = adaptive; } + public Boolean isDynamicSources() { + return this.dynamicSources; + } + + public void setDynamicSources(Boolean dynamicSources) { + this.dynamicSources = dynamicSources; + } + } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationTests.java index f6f0c827b199..443c213ab608 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationTests.java @@ -25,6 +25,7 @@ import io.lettuce.core.ClientOptions; import io.lettuce.core.cluster.ClusterClientOptions; +import io.lettuce.core.cluster.ClusterTopologyRefreshOptions; import io.lettuce.core.cluster.ClusterTopologyRefreshOptions.RefreshTrigger; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.junit.jupiter.api.Test; @@ -312,6 +313,36 @@ void testRedisConfigurationWithClusterRefreshPeriodHasNoEffectWithNonClusteredCo ClientOptions.class, (options) -> assertThat(options.getClass()).isEqualTo(ClientOptions.class))); } + @Test + void testRedisConfigurationWithClusterDynamicSourcesEnabled() { + this.contextRunner + .withPropertyValues("spring.redis.cluster.nodes=127.0.0.1:27379,127.0.0.1:27380", + "spring.redis.lettuce.cluster.refresh.dynamic-sources=true") + .run(assertClientOptions(ClusterClientOptions.class, + (options) -> assertThat(options.getTopologyRefreshOptions().useDynamicRefreshSources()) + .isTrue())); + } + + @Test + void testRedisConfigurationWithClusterDynamicSourcesDisabled() { + this.contextRunner + .withPropertyValues("spring.redis.cluster.nodes=127.0.0.1:27379,127.0.0.1:27380", + "spring.redis.lettuce.cluster.refresh.dynamic-sources=false") + .run(assertClientOptions(ClusterClientOptions.class, + (options) -> assertThat(options.getTopologyRefreshOptions().useDynamicRefreshSources()) + .isFalse())); + } + + @Test + void testRedisConfigurationWithClusterDynamicSourcesUnspecifiedUsesDefault() { + this.contextRunner + .withPropertyValues("spring.redis.cluster.nodes=127.0.0.1:27379,127.0.0.1:27380", + "spring.redis.lettuce.cluster.refresh.dynamic-sources=") + .run(assertClientOptions(ClusterClientOptions.class, + (options) -> assertThat(options.getTopologyRefreshOptions().useDynamicRefreshSources()) + .isEqualTo(ClusterTopologyRefreshOptions.DEFAULT_DYNAMIC_REFRESH_SOURCES))); + } + private ContextConsumer assertClientOptions( Class expectedType, Consumer options) { return (context) -> {