From 4e903113c7ef2449b0061dace35494a7b8d83482 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, 42 insertions(+), 18 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 c662aff99..31aae3915 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. @@ -61,6 +61,7 @@ import org.springframework.util.ObjectUtils; import com.lambdaworks.redis.KeyValue; import com.lambdaworks.redis.RedisException; +import com.lambdaworks.redis.RedisURI; import com.lambdaworks.redis.api.StatefulConnection; import com.lambdaworks.redis.cluster.RedisClusterClient; import com.lambdaworks.redis.cluster.SlotHash; @@ -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.8.7 + */ + 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 f08447d8f..370ca0d09 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; @@ -201,7 +200,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() { @@ -577,7 +576,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 a1573a2ed..3ef27b3c7 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 @@ -32,11 +32,14 @@ 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; import com.lambdaworks.redis.RedisURI; import com.lambdaworks.redis.cluster.RedisClusterClient; +import org.springframework.test.util.ReflectionTestUtils; + /** * @author Christoph Strobl @@ -275,4 +278,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))); + } }