diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettuceClientConfiguration.java b/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettuceClientConfiguration.java index 5809909d8..62439de47 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettuceClientConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettuceClientConfiguration.java @@ -42,11 +42,13 @@ class DefaultLettuceClientConfiguration implements LettuceClientConfiguration { private final Optional readFrom; private final Duration timeout; private final Duration shutdownTimeout; + private final Duration shutdownQuietPeriod; DefaultLettuceClientConfiguration(boolean useSsl, boolean verifyPeer, boolean startTls, @Nullable ClientResources clientResources, @Nullable ClientOptions clientOptions, @Nullable String clientName, @Nullable ReadFrom readFrom, - Duration timeout, Duration shutdownTimeout) { + Duration timeout, Duration shutdownTimeout, + @Nullable Duration shutdownQuietPeriod) { this.useSsl = useSsl; this.verifyPeer = verifyPeer; @@ -57,6 +59,7 @@ class DefaultLettuceClientConfiguration implements LettuceClientConfiguration { this.readFrom = Optional.ofNullable(readFrom); this.timeout = timeout; this.shutdownTimeout = shutdownTimeout; + this.shutdownQuietPeriod = shutdownQuietPeriod != null ? shutdownQuietPeriod : shutdownTimeout; } /* @@ -139,4 +142,13 @@ class DefaultLettuceClientConfiguration implements LettuceClientConfiguration { public Duration getShutdownTimeout() { return shutdownTimeout; } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration#getShutdownQuietPeriod() + */ + @Override + public Duration getShutdownQuietPeriod() { + return shutdownQuietPeriod; + } } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePoolingClientConfiguration.java b/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePoolingClientConfiguration.java index 168aacc39..9a20607eb 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePoolingClientConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePoolingClientConfiguration.java @@ -124,6 +124,15 @@ class DefaultLettucePoolingClientConfiguration implements LettucePoolingClientCo return clientConfiguration.getShutdownTimeout(); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration#getShutdownQuietPeriod() + */ + @Override + public Duration getShutdownQuietPeriod() { + return clientConfiguration.getShutdownQuietPeriod(); + } + /* * (non-Javadoc) * @see org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration.LettucePoolingClientConfiguration#getPoolConfig() diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClientConfiguration.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClientConfiguration.java index f8a515e5e..4d822fcec 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClientConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceClientConfiguration.java @@ -103,6 +103,13 @@ public interface LettuceClientConfiguration { */ Duration getShutdownTimeout(); + /** + * @return the shutdown quiet period used to close the client. + * @since 2.2 + * @see io.lettuce.core.AbstractRedisClient#shutdown(long, long, TimeUnit) + */ + Duration getShutdownQuietPeriod(); + /** * Creates a new {@link LettuceClientConfigurationBuilder} to build {@link LettuceClientConfiguration} to be used with * the Lettuce client. @@ -157,6 +164,7 @@ public interface LettuceClientConfiguration { @Nullable ReadFrom readFrom; Duration timeout = Duration.ofSeconds(RedisURI.DEFAULT_TIMEOUT); Duration shutdownTimeout = Duration.ofMillis(100); + @Nullable Duration shutdownQuietPeriod; LettuceClientConfigurationBuilder() {} @@ -258,12 +266,28 @@ public interface LettuceClientConfiguration { */ public LettuceClientConfigurationBuilder shutdownTimeout(Duration shutdownTimeout) { - Assert.notNull(timeout, "Duration must not be null!"); + Assert.notNull(shutdownTimeout, "Duration must not be null!"); this.shutdownTimeout = shutdownTimeout; return this; } + /** + * Configure a shutdown timeout. + * + * @param shutdownQuietPeriod must not be {@literal null}. + * @return {@literal this} builder. + * @throws IllegalArgumentException if shutdownQuietPeriod is {@literal null}. + * @since 2.2 + */ + public LettuceClientConfigurationBuilder shutdownQuietPeriod(Duration shutdownQuietPeriod) { + + Assert.notNull(shutdownQuietPeriod, "Duration must not be null!"); + + this.shutdownQuietPeriod = shutdownQuietPeriod; + return this; + } + /** * Build the {@link LettuceClientConfiguration} with the configuration applied from this builder. * @@ -272,7 +296,7 @@ public interface LettuceClientConfiguration { public LettuceClientConfiguration build() { return new DefaultLettuceClientConfiguration(useSsl, verifyPeer, startTls, clientResources, clientOptions, - clientName, readFrom, timeout, shutdownTimeout); + clientName, readFrom, timeout, shutdownTimeout, shutdownQuietPeriod); } } 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 b42934339..957f294c0 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 @@ -302,8 +302,9 @@ public class LettuceConnectionFactory } try { + Duration quietPeriod = clientConfiguration.getShutdownQuietPeriod(); Duration timeout = clientConfiguration.getShutdownTimeout(); - client.shutdown(timeout.toMillis(), timeout.toMillis(), TimeUnit.MILLISECONDS); + client.shutdown(quietPeriod.toMillis(), timeout.toMillis(), TimeUnit.MILLISECONDS); } catch (Exception e) { if (log.isWarnEnabled()) { @@ -1276,5 +1277,14 @@ public class LettuceConnectionFactory void setShutdownTimeout(Duration shutdownTimeout) { this.shutdownTimeout = shutdownTimeout; } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration#getShutdownQuietPeriod() + */ + @Override + public Duration getShutdownQuietPeriod() { + return shutdownTimeout; + } } } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettucePoolingClientConfiguration.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettucePoolingClientConfiguration.java index a293efa3b..23fc6921d 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettucePoolingClientConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettucePoolingClientConfiguration.java @@ -142,6 +142,17 @@ public interface LettucePoolingClientConfiguration extends LettuceClientConfigur return this; } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration.LettuceClientConfigurationBuilder#shutdownQuietPeriod(java.time.Duration) + */ + @Override + public LettucePoolingClientConfigurationBuilder shutdownQuietPeriod(Duration shutdownQuietPeriod) { + + super.shutdownQuietPeriod(shutdownQuietPeriod); + return this; + } + /** * Set the {@link GenericObjectPoolConfig} used by the driver. * diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceClientConfigurationUnitTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceClientConfigurationUnitTests.java index 71cf15b00..3c43bf41b 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceClientConfigurationUnitTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceClientConfigurationUnitTests.java @@ -45,6 +45,7 @@ public class LettuceClientConfigurationUnitTests { assertThat(configuration.getClientName()).isEmpty(); assertThat(configuration.getCommandTimeout()).isEqualTo(Duration.ofSeconds(60)); assertThat(configuration.getShutdownTimeout()).isEqualTo(Duration.ofMillis(100)); + assertThat(configuration.getShutdownQuietPeriod()).isEqualTo(Duration.ofMillis(100)); } @Test // DATAREDIS-574, DATAREDIS-576, DATAREDIS-667 @@ -62,6 +63,7 @@ public class LettuceClientConfigurationUnitTests { .clientName("foo") // .commandTimeout(Duration.ofMinutes(5)) // .shutdownTimeout(Duration.ofHours(2)) // + .shutdownQuietPeriod(Duration.ofMinutes(5)) // .build(); assertThat(configuration.isUseSsl()).isTrue(); @@ -72,6 +74,7 @@ public class LettuceClientConfigurationUnitTests { assertThat(configuration.getClientName()).contains("foo"); assertThat(configuration.getCommandTimeout()).isEqualTo(Duration.ofMinutes(5)); assertThat(configuration.getShutdownTimeout()).isEqualTo(Duration.ofHours(2)); + assertThat(configuration.getShutdownQuietPeriod()).isEqualTo(Duration.ofMinutes(5)); } @Test(expected = IllegalArgumentException.class) // DATAREDIS-576 diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettucePoolingClientConfigurationUnitTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettucePoolingClientConfigurationUnitTests.java index e320a74ef..3071a0200 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettucePoolingClientConfigurationUnitTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettucePoolingClientConfigurationUnitTests.java @@ -46,6 +46,7 @@ public class LettucePoolingClientConfigurationUnitTests { assertThat(configuration.getClientResources()).isEmpty(); assertThat(configuration.getCommandTimeout()).isEqualTo(Duration.ofSeconds(60)); assertThat(configuration.getShutdownTimeout()).isEqualTo(Duration.ofMillis(100)); + assertThat(configuration.getShutdownQuietPeriod()).isEqualTo(Duration.ofMillis(100)); } @Test // DATAREDIS-667 @@ -64,6 +65,7 @@ public class LettucePoolingClientConfigurationUnitTests { .clientResources(sharedClientResources) // .commandTimeout(Duration.ofMinutes(5)) // .shutdownTimeout(Duration.ofHours(2)) // + .shutdownQuietPeriod(Duration.ofMinutes(5)) // .build(); assertThat(configuration.getPoolConfig()).isEqualTo(poolConfig); @@ -74,5 +76,6 @@ public class LettucePoolingClientConfigurationUnitTests { assertThat(configuration.getClientResources()).contains(sharedClientResources); assertThat(configuration.getCommandTimeout()).isEqualTo(Duration.ofMinutes(5)); assertThat(configuration.getShutdownTimeout()).isEqualTo(Duration.ofHours(2)); + assertThat(configuration.getShutdownQuietPeriod()).isEqualTo(Duration.ofMinutes(5)); } }