diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java b/src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java index 35f9b5404b..9a52613af8 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java @@ -30,6 +30,7 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Bharat Agarwal * @since 2.0 */ class DefaultJedisClientConfiguration implements JedisClientConfiguration { @@ -44,11 +45,13 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration { private final Optional clientName; private final Duration readTimeout; private final Duration connectTimeout; + private final Optional topologyRefreshPeriod; DefaultJedisClientConfiguration(@Nullable JedisClientConfigBuilderCustomizer customizer, boolean useSsl, @Nullable SSLSocketFactory sslSocketFactory, @Nullable SSLParameters sslParameters, @Nullable HostnameVerifier hostnameVerifier, boolean usePooling, @Nullable GenericObjectPoolConfig poolConfig, - @Nullable String clientName, Duration readTimeout, Duration connectTimeout) { + @Nullable String clientName, Duration readTimeout, Duration connectTimeout, + @Nullable Duration topologyRefreshPeriod) { this.customizer = Optional.ofNullable(customizer); this.useSsl = useSsl; @@ -60,6 +63,7 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration { this.clientName = Optional.ofNullable(clientName); this.readTimeout = readTimeout; this.connectTimeout = connectTimeout; + this.topologyRefreshPeriod = Optional.ofNullable(topologyRefreshPeriod); } @Override @@ -111,4 +115,8 @@ public Duration getReadTimeout() { public Duration getConnectTimeout() { return connectTimeout; } + @Override + public Optional getTopologyRefreshPeriod() { + return topologyRefreshPeriod; + } } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java index 17766bf423..391df78ad6 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java @@ -45,11 +45,13 @@ *
  • Optional client name
  • *
  • Connect {@link Duration timeout}
  • *
  • Read {@link Duration timeout}
  • + *
  • Optional {@link Duration topologyRefreshPeriod} * * * @author Mark Paluch * @author Christoph Strobl * @author Chao Chang + * @author Bharat Agarwal * @since 2.0 * @see redis.clients.jedis.Jedis * @see org.springframework.data.redis.connection.RedisStandaloneConfiguration @@ -112,6 +114,14 @@ public interface JedisClientConfiguration { */ Duration getReadTimeout(); + /** + * @return the optional {@link Duration} for Topology Refresh. + * Applies only to Redis Cluster mode. Standalone and Sentinel mode of cluster enabled redis doesn't use or require this. + * Default value is null i.e. Jedis doesn't do periodical topology refresh, else Jedis will refresh node topology every duration mentioned. + */ + + Optional getTopologyRefreshPeriod(); + /** * Creates a new {@link JedisClientConfigurationBuilder} to build {@link JedisClientConfiguration} to be used with the * jedis client. @@ -137,6 +147,8 @@ static JedisClientConfigurationBuilder builder() { *
    2000 msec
    *
    Connect Timeout
    *
    2000 msec
    + *
    Topology Refresh Period
    + *
    null
    * * * @return a {@link JedisClientConfiguration} with defaults. @@ -203,6 +215,22 @@ interface JedisClientConfigurationBuilder { */ JedisClientConfigurationBuilder connectTimeout(Duration connectTimeout); + + /** + * Configure a topology refresh period + *

    + * Topology Refresh Period is used by Jedis to refresh topology of nodes on periodically basis. + * Default value is null i.e. doesn't do periodically refresh. + *

    + * Applies only to Cluster mode redis. Standalone or Sentinal redis clusters doesn't have impact of this configuration. + * + * @param topologyRefreshPeriod + * @return {@literal this} builder. + */ + JedisClientConfigurationBuilder topologyRefreshPeriod(Duration topologyRefreshPeriod); + + + /** * Build the {@link JedisClientConfiguration} with the configuration applied from this builder. * @@ -296,6 +324,7 @@ class DefaultJedisClientConfigurationBuilder implements JedisClientConfiguration private @Nullable String clientName; private Duration readTimeout = Duration.ofMillis(Protocol.DEFAULT_TIMEOUT); private Duration connectTimeout = Duration.ofMillis(Protocol.DEFAULT_TIMEOUT); + private @Nullable Duration topologyRefreshPeriod = null; // Maintaing default value as Jedis has to keep backward compatibility private DefaultJedisClientConfigurationBuilder() {} @@ -390,11 +419,18 @@ public JedisClientConfigurationBuilder connectTimeout(Duration connectTimeout) { return this; } + + @Override + public JedisClientConfigurationBuilder topologyRefreshPeriod(Duration topologyRefreshPeriod) { + this.topologyRefreshPeriod = topologyRefreshPeriod; + return this; + } + @Override public JedisClientConfiguration build() { return new DefaultJedisClientConfiguration(customizer, useSsl, sslSocketFactory, sslParameters, hostnameVerifier, - usePooling, poolConfig, clientName, readTimeout, connectTimeout); + usePooling, poolConfig, clientName, readTimeout, connectTimeout, topologyRefreshPeriod); } } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java index 092fa4d391..3780197a3a 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java @@ -93,6 +93,7 @@ * @author Mark Paluch * @author Fu Jian * @author Ajith Kumar + * @author Bharat Agarwal * @see JedisClientConfiguration * @see Jedis */ @@ -846,7 +847,11 @@ protected JedisCluster createCluster(RedisClusterConfiguration clusterConfig, int redirects = clusterConfig.getMaxRedirects() != null ? clusterConfig.getMaxRedirects() : 5; - return new JedisCluster(hostAndPort, this.clientConfig, redirects, poolConfig); + // When maxTotalRetriesDuration passed, Jedis use this method to calcuate, to use topologyRefreshPeriod, Jedis constructor expect maxTotalRetriesDuration. + Duration maxTotalRetriesDuration = Duration.ofMillis((long)this.clientConfig.getSocketTimeoutMillis() * (long)redirects); + Duration topologyRefreshPeriod = this.clientConfiguration.getTopologyRefreshPeriod().orElse(null); + + return new JedisCluster(hostAndPort, this.clientConfig, poolConfig, topologyRefreshPeriod, redirects, maxTotalRetriesDuration); } @Override @@ -1093,6 +1098,7 @@ static class MutableJedisClientConfiguration implements JedisClientConfiguration private @Nullable String clientName; private Duration readTimeout = Duration.ofMillis(Protocol.DEFAULT_TIMEOUT); private Duration connectTimeout = Duration.ofMillis(Protocol.DEFAULT_TIMEOUT); + private @Nullable Duration topologyRefreshPeriod = null; public static JedisClientConfiguration create(GenericObjectPoolConfig jedisPoolConfig) { @@ -1186,5 +1192,10 @@ public Duration getConnectTimeout() { public void setConnectTimeout(Duration connectTimeout) { this.connectTimeout = connectTimeout; } + + @Override + public Optional getTopologyRefreshPeriod() { + return Optional.empty(); + } } } diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisClientConfigurationUnitTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisClientConfigurationUnitTests.java index 74203c8bc1..31d3c93628 100644 --- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisClientConfigurationUnitTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisClientConfigurationUnitTests.java @@ -49,6 +49,7 @@ void shouldCreateEmptyConfiguration() { assertThat(configuration.getPoolConfig()).isPresent(); assertThat(configuration.getSslParameters()).isEmpty(); assertThat(configuration.getSslSocketFactory()).isEmpty(); + assertThat(configuration.getTopologyRefreshPeriod()).isEmpty(); } @Test // DATAREDIS-574 @@ -64,6 +65,7 @@ void shouldConfigureAllProperties() throws NoSuchAlgorithmException { .sslParameters(sslParameters) // .sslSocketFactory(socketFactory).and() // .clientName("my-client") // + .topologyRefreshPeriod(Duration.ofMillis(100)) // adding topologyRefreshPeriod .connectTimeout(Duration.ofMinutes(10)) // .readTimeout(Duration.ofHours(5)) // .usePooling().poolConfig(poolConfig) // @@ -79,6 +81,8 @@ void shouldConfigureAllProperties() throws NoSuchAlgorithmException { assertThat(configuration.getReadTimeout()).isEqualTo(Duration.ofHours(5)); assertThat(configuration.getPoolConfig()).contains(poolConfig); + + assertThat(configuration.getTopologyRefreshPeriod()).isEqualTo(Duration.ofMillis(100)); } enum MyHostnameVerifier implements HostnameVerifier {