diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java index 56edf01bc..0bb386c38 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java @@ -979,7 +979,8 @@ public class LettuceConnectionFactory if (isClusterAware()) { List initialUris = new ArrayList<>(); - for (RedisNode node : ((ClusterConfiguration) configuration).getClusterNodes()) { + ClusterConfiguration configuration = (ClusterConfiguration) this.configuration; + for (RedisNode node : configuration.getClusterNodes()) { initialUris.add(createRedisURIAndApplySettings(node.getHost(), node.getPort())); } @@ -987,9 +988,7 @@ public class LettuceConnectionFactory .map(clientResources -> RedisClusterClient.create(clientResources, initialUris)) // .orElseGet(() -> RedisClusterClient.create(initialUris)); - clientConfiguration.getClientOptions() // - .filter(clientOptions -> clientOptions instanceof ClusterClientOptions) // - .ifPresent(clientOptions -> clusterClient.setOptions((ClusterClientOptions) clientOptions)); + clusterClient.setOptions(getClusterClientOptions(configuration)); return clusterClient; } @@ -1006,6 +1005,41 @@ public class LettuceConnectionFactory return redisClient; } + private ClusterClientOptions getClusterClientOptions(ClusterConfiguration configuration) { + + Optional clientOptions = clientConfiguration.getClientOptions(); + ClusterClientOptions clusterClientOptions = clientOptions // + .filter(ClusterClientOptions.class::isInstance) // + .map(ClusterClientOptions.class::cast) // + .orElseGet(() -> { + return clientOptions // + .map(LettuceConnectionFactory::toClusterClientOptions) // + .orElseGet(ClusterClientOptions::create); + }); + + if (configuration.getMaxRedirects() != null) { + return clusterClientOptions.mutate().maxRedirects(configuration.getMaxRedirects()).build(); + } + + return clusterClientOptions; + } + + // TODO: Replace with Lettuce 5.1.6 ClusterClientOptions.builder(ClientOptions) + private static ClusterClientOptions toClusterClientOptions(ClientOptions it) { + + return ClusterClientOptions.builder() // + .autoReconnect(it.isAutoReconnect()) // + .cancelCommandsOnReconnectFailure(it.isCancelCommandsOnReconnectFailure()) // + .disconnectedBehavior(it.getDisconnectedBehavior()) // + .pingBeforeActivateConnection(it.isPingBeforeActivateConnection()) // + .requestQueueSize(it.getRequestQueueSize()) // + .socketOptions(it.getSocketOptions()) // + .sslOptions(it.getSslOptions()) // + .suspendReconnectOnProtocolFailure(it.isSuspendReconnectOnProtocolFailure())// + .timeoutOptions(it.getTimeoutOptions()) // + .build(); + } + private RedisURI getSentinelRedisURI() { RedisURI redisUri = LettuceConverters.sentinelConfigurationToRedisURI( diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryUnitTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryUnitTests.java index 811de26b0..b70020766 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryUnitTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryUnitTests.java @@ -21,6 +21,7 @@ import static org.hamcrest.core.IsInstanceOf.*; import static org.hamcrest.core.IsNull.*; import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import static org.mockito.Mockito.any; import static org.springframework.data.redis.connection.ClusterTestVariables.*; import static org.springframework.data.redis.connection.RedisConfiguration.*; import static org.springframework.data.redis.connection.lettuce.LettuceTestClientResources.*; @@ -32,6 +33,7 @@ import io.lettuce.core.RedisClient; import io.lettuce.core.RedisURI; import io.lettuce.core.api.StatefulConnection; import io.lettuce.core.api.StatefulRedisConnection; +import io.lettuce.core.cluster.ClusterClientOptions; import io.lettuce.core.cluster.RedisClusterClient; import io.lettuce.core.cluster.api.StatefulRedisClusterConnection; import io.lettuce.core.codec.ByteArrayCodec; @@ -711,6 +713,49 @@ public class LettuceConnectionFactoryUnitTests { assertThat(redisUri.getDatabase(), is(equalTo(1))); } + @Test // DATAREDIS-949 + public void maxRedirectsShouldBeSetOnClientOptions() { + + RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(); + clusterConfiguration.clusterNode("localhost", 1234).setMaxRedirects(42); + + LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(clusterConfiguration, + LettuceClientConfiguration.defaultConfiguration()); + connectionFactory.afterPropertiesSet(); + ConnectionFactoryTracker.add(connectionFactory); + + RedisClusterClient client = (RedisClusterClient) getField(connectionFactory, "client"); + + ClusterClientOptions options = (ClusterClientOptions) client.getOptions(); + + assertThat(options.getMaxRedirects(), is(42)); + assertThat(options.isValidateClusterNodeMembership(), is(true)); + assertThat(options.getTimeoutOptions().isApplyConnectionTimeout(), is(true)); + } + + @Test // DATAREDIS-949 + public void maxRedirectsShouldBeSetOnClusterClientOptions() { + + RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(); + clusterConfiguration.clusterNode("localhost", 1234).setMaxRedirects(42); + + LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder() + .clientOptions(ClusterClientOptions.builder().validateClusterNodeMembership(false).build()).build(); + + LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(clusterConfiguration, + clientConfiguration); + connectionFactory.afterPropertiesSet(); + ConnectionFactoryTracker.add(connectionFactory); + + RedisClusterClient client = (RedisClusterClient) getField(connectionFactory, "client"); + + ClusterClientOptions options = (ClusterClientOptions) client.getOptions(); + + assertThat(options.getMaxRedirects(), is(42)); + assertThat(options.isValidateClusterNodeMembership(), is(false)); + assertThat(options.getTimeoutOptions().isApplyConnectionTimeout(), is(false)); + } + @Data @AllArgsConstructor static class CustomRedisConfiguration implements RedisConfiguration, WithHostAndPort {