DATAREDIS-949 - Consider max-redirects using Lettuce.

LettuceConnectionFactory now considers the maximal redirection limit for Redis Cluster redirections.

Previously, the max-redirects limit was not configured in Lettuce.

Original Pull Request: #417
This commit is contained in:
Mark Paluch
2019-03-21 11:43:59 +02:00
committed by Christoph Strobl
parent d694b63503
commit 2cb3e056b1
2 changed files with 85 additions and 4 deletions

View File

@@ -948,7 +948,8 @@ public class LettuceConnectionFactory
if (isClusterAware()) {
List<RedisURI> 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()));
}
@@ -956,9 +957,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;
}
@@ -975,6 +974,41 @@ public class LettuceConnectionFactory
return redisClient;
}
private ClusterClientOptions getClusterClientOptions(ClusterConfiguration configuration) {
Optional<ClientOptions> 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(

View File

@@ -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.*;
@@ -30,6 +31,9 @@ import io.lettuce.core.AbstractRedisClient;
import io.lettuce.core.ClientOptions;
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;
@@ -684,6 +688,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 {