From 1210f84894a055ab127e62647e49089b3a4eb455 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 18 Aug 2017 09:34:35 +0200 Subject: [PATCH] DATAREDIS-676 - Pass on configured command timeout to LettuceClusterConnection. We now not only configure the underlying lettuce connection with the command timeout set via the connection factory, but also make sure to pass the option on to the LettuceClusterConnection. Original pull request: #266. --- .../lettuce/LettuceClusterConnection.java | 39 ++++++++++++------- .../lettuce/LettuceConnectionFactory.java | 8 ++-- .../LettuceConnectionFactoryUnitTests.java | 13 ++++++- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java index 0fc7264ab..ad19bfaf6 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnection.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -65,6 +65,7 @@ import com.lambdaworks.redis.RedisAsyncConnectionImpl; import com.lambdaworks.redis.RedisClusterConnection; import com.lambdaworks.redis.RedisConnection; import com.lambdaworks.redis.RedisException; +import com.lambdaworks.redis.RedisURI; import com.lambdaworks.redis.cluster.RedisClusterClient; import com.lambdaworks.redis.cluster.SlotHash; import com.lambdaworks.redis.cluster.models.partitions.Partitions; @@ -87,36 +88,46 @@ public class LettuceClusterConnection extends LettuceConnection private final RedisClusterClient clusterClient; private ClusterCommandExecutor clusterCommandExecutor; private ClusterTopologyProvider topologyProvider; - private final boolean disposeClusterCommandExecutorOnClose; + private boolean disposeClusterCommandExecutorOnClose; /** - * Creates new {@link LettuceClusterConnection} using {@link RedisClusterClient}. + * Creates new {@link LettuceClusterConnection} using {@link RedisClusterClient} with default + * {@link RedisURI#DEFAULT_TIMEOUT timeout} and a fresh {@link ClusterCommandExecutor} that gets destroyed on close. * * @param clusterClient must not be {@literal null}. */ public LettuceClusterConnection(RedisClusterClient clusterClient) { - super(null, 100, clusterClient, null, 0); + this(clusterClient, RedisURI.DEFAULT_TIMEOUT, + new ClusterCommandExecutor(new LettuceClusterTopologyProvider(clusterClient), + new LettuceClusterNodeResourceProvider(clusterClient), exceptionConverter)); - Assert.notNull(clusterClient, "RedisClusterClient must not be null."); - - this.clusterClient = clusterClient; - topologyProvider = new LettuceClusterTopologyProvider(clusterClient); - clusterCommandExecutor = new ClusterCommandExecutor(topologyProvider, - new LettuceClusterNodeResourceProvider(clusterClient), exceptionConverter); - disposeClusterCommandExecutorOnClose = true; + this.disposeClusterCommandExecutorOnClose = true; } /** - * Creates new {@link LettuceClusterConnection} using {@link RedisClusterClient} running commands across the cluster - * via given {@link ClusterCommandExecutor}. + * Creates new {@link LettuceClusterConnection} with default {@link RedisURI#DEFAULT_TIMEOUT timeout} using + * {@link RedisClusterClient} running commands across the cluster via given {@link ClusterCommandExecutor}. * * @param clusterClient must not be {@literal null}. * @param executor must not be {@literal null}. */ public LettuceClusterConnection(RedisClusterClient clusterClient, ClusterCommandExecutor executor) { + this(clusterClient, RedisURI.DEFAULT_TIMEOUT, executor); + } - super(null, 100, clusterClient, null, 0); + /** + * Creates new {@link LettuceClusterConnection} with given command {@code timeout} using {@link RedisClusterClient} + * running commands across the cluster via given {@link ClusterCommandExecutor}. + * + * @param clusterClient must not be {@literal null}. + * @param timeout command timeout (in milliseconds) + * @param executor must not be {@literal null}. + * @since 1.7.12 + */ + public LettuceClusterConnection(RedisClusterClient clusterClient, long timeout, ClusterCommandExecutor executor) { + + super(null, timeout, clusterClient, null, 0); Assert.notNull(clusterClient, "RedisClusterClient must not be null."); Assert.notNull(executor, "ClusterCommandExecutor must not be null."); 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 8d5387bd5..77c1f848e 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 @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2011-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection.lettuce; import java.util.ArrayList; @@ -203,7 +202,7 @@ public class LettuceConnectionFactory implements InitializingBean, DisposableBea throw new InvalidDataAccessApiUsageException("Cluster is not configured!"); } - return new LettuceClusterConnection((RedisClusterClient) client, clusterCommandExecutor); + return new LettuceClusterConnection((RedisClusterClient) client, getTimeout(), clusterCommandExecutor); } public void initConnection() { @@ -566,7 +565,8 @@ public class LettuceConnectionFactory implements InitializingBean, DisposableBea } RedisClusterClient clusterClient = clientResources != null - ? RedisClusterClient.create(clientResources, initialUris) : RedisClusterClient.create(initialUris); + ? RedisClusterClient.create(clientResources, initialUris) + : RedisClusterClient.create(initialUris); this.clusterCommandExecutor = new ClusterCommandExecutor( new LettuceClusterConnection.LettuceClusterTopologyProvider(clusterClient), 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 6c7344533..cee073b74 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 @@ -1,5 +1,5 @@ /* - * Copyright 2015-2016 the original author or authors. + * Copyright 2015-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +32,7 @@ import org.junit.Test; import org.springframework.data.redis.ConnectionFactoryTracker; import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisSentinelConfiguration; +import org.springframework.test.util.ReflectionTestUtils; import com.lambdaworks.redis.AbstractRedisClient; import com.lambdaworks.redis.RedisClient; @@ -311,4 +312,14 @@ public class LettuceConnectionFactoryUnitTests { assertThat(uri.isVerifyPeer(), is(true)); } } + + @Test // DATAREDIS-676 + public void timeoutShouldBePassedOnToClusterConnection() { + + LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(clusterConfig); + connectionFactory.setTimeout(2000); + connectionFactory.afterPropertiesSet(); + + assertThat((Long) ReflectionTestUtils.getField(connectionFactory.getClusterConnection(), "timeout"), is(equalTo(2000L))); + } }