From 9de4b7f15a239c7e994d5006a11924ef964fadcd Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 1 Sep 2023 11:41:22 +0200 Subject: [PATCH] Polishing #2082 Add author and since, tags. Add Javadoc. Original pull request: #2499 --- .../io/lettuce/core/ConnectionBuilder.java | 26 +++--- .../java/io/lettuce/core/SocketOptions.java | 91 +++++++++++++++---- 2 files changed, 90 insertions(+), 27 deletions(-) diff --git a/src/main/java/io/lettuce/core/ConnectionBuilder.java b/src/main/java/io/lettuce/core/ConnectionBuilder.java index 2c0429cd20..0cebea9f55 100644 --- a/src/main/java/io/lettuce/core/ConnectionBuilder.java +++ b/src/main/java/io/lettuce/core/ConnectionBuilder.java @@ -55,6 +55,7 @@ * Connection builder for connections. This class is part of the internal API. * * @author Mark Paluch + * @author Bodong Ybd */ public class ConnectionBuilder { @@ -263,8 +264,22 @@ public void configureBootstrap(boolean domainSocket, bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Math.toIntExact(options.getConnectTimeout().toMillis())); if (!domainSocket) { + bootstrap.option(ChannelOption.SO_KEEPALIVE, options.isKeepAlive()); bootstrap.option(ChannelOption.TCP_NODELAY, options.isTcpNoDelay()); + + if (options.isEnableTcpUserTimeout()) { + + SocketOptions.TcpUserTimeoutOptions tcpUserTimeoutOptions = options.getTcpUserTimeout(); + + if (IOUringProvider.isAvailable()) { + IOUringProvider.applyTcpUserTimeout(bootstrap, tcpUserTimeoutOptions.getTcpUserTimeout()); + } else if (io.lettuce.core.resource.EpollProvider.isAvailable()) { + EpollProvider.applyTcpUserTimeout(bootstrap, tcpUserTimeoutOptions.getTcpUserTimeout()); + } else { + logger.warn("Cannot apply TCP User Timeout options to channel type " + channelClass.getName()); + } + } } bootstrap.channel(channelClass).group(eventLoopGroup); @@ -285,17 +300,6 @@ public void configureBootstrap(boolean domainSocket, } } - if (options.isEnableTcpUserTimeout()) { - SocketOptions.TcpUserTimeoutOptions tcpUserTimeoutOptions = options.getTcpUserTimeout(); - - if (IOUringProvider.isAvailable()) { - IOUringProvider.applyTcpUserTimeout(bootstrap, tcpUserTimeoutOptions.getTcpUserTimeout()); - } else if (io.lettuce.core.resource.EpollProvider.isAvailable()) { - EpollProvider.applyTcpUserTimeout(bootstrap, tcpUserTimeoutOptions.getTcpUserTimeout()); - } else { - logger.warn("Cannot apply tcp user timeout options to channel type " + channelClass.getName()); - } - } } public RedisChannelHandler connection() { diff --git a/src/main/java/io/lettuce/core/SocketOptions.java b/src/main/java/io/lettuce/core/SocketOptions.java index fbc6e49a79..7fa4d3c6bb 100644 --- a/src/main/java/io/lettuce/core/SocketOptions.java +++ b/src/main/java/io/lettuce/core/SocketOptions.java @@ -24,6 +24,7 @@ * Options to configure low-level socket options for the connections kept to Redis servers. * * @author Mark Paluch + * @author Bodong Ybd * @since 4.3 */ public class SocketOptions { @@ -64,7 +65,7 @@ protected SocketOptions(SocketOptions original) { this.keepAlive = original.getKeepAlive(); this.extendedKeepAlive = original.isExtendedKeepAlive(); this.tcpNoDelay = original.isTcpNoDelay(); - this.tcpUserTimeout = original.tcpUserTimeout; + this.tcpUserTimeout = original.getTcpUserTimeout(); } /** @@ -104,8 +105,8 @@ public static class Builder { private KeepAliveOptions keepAlive = KeepAliveOptions.builder().enable(DEFAULT_SO_KEEPALIVE).build(); - private TcpUserTimeoutOptions tcpUserTimeout = TcpUserTimeoutOptions.builder() - .enable(DEFAULT_TCP_USER_TIMEOUT_ENABLED).build(); + private TcpUserTimeoutOptions tcpUserTimeout = TcpUserTimeoutOptions.builder().enable(DEFAULT_TCP_USER_TIMEOUT_ENABLED) + .build(); private boolean tcpNoDelay = DEFAULT_SO_NO_DELAY; @@ -183,8 +184,17 @@ public Builder keepAlive(KeepAliveOptions keepAlive) { return this; } + /** + * Configure TCP User Timeout. Defaults to disabled. See {@link #DEFAULT_TCP_USER_TIMEOUT_ENABLED}. + * + * @param tcpUserTimeout the TCP User Timeout options. + * @return {@code this} + * @since 6.2.7 + * @see TcpUserTimeoutOptions + */ public Builder tcpUserTimeout(TcpUserTimeoutOptions tcpUserTimeout) { - LettuceAssert.notNull(tcpUserTimeout, "tcpUserTimeout options must not be null"); + + LettuceAssert.notNull(tcpUserTimeout, "TcpUserTimeout options must not be null"); this.tcpUserTimeout = tcpUserTimeout; @@ -349,8 +359,8 @@ private Builder() { } /** - * Set the maximum number of keepalive probes TCP should send before dropping the connection. Defaults to - * {@code 9}. See also {@link #DEFAULT_COUNT} and {@code TCP_KEEPCNT}. + * Set the maximum number of keepalive probes TCP should send before dropping the connection. Defaults to {@code 9}. + * See also {@link #DEFAULT_COUNT} and {@code TCP_KEEPCNT}. * * @param count the maximum number of keepalive probes TCP * @return {@code this} @@ -509,15 +519,17 @@ public Duration getInterval() { } /** - * TCP_USER_TIMEOUT TCP_USER_TIMEOUT comes from RFC5482 - * , configuring this parameter can allow the user TCP to initiate a reconnection to solve this problem when the - * network is abnormal: #2082 + * TCP_USER_TIMEOUT comes from RFC5482 , configuring this + * parameter can allow the user TCP to initiate a reconnection to solve this problem when the network is abnormal. + *

+ * The timeout is currently only supported with epoll and io_uring native transports. + * + * @since 6.2.7 */ public static class TcpUserTimeoutOptions { /** - * Recommended default TCP_USER_TIMEOUT == TCP_KEEPIDLE(2 hour) + TCP_KEEPINTVL(75 s) * TCP_KEEPCNT(9) - * 2 * 3600 + 75 * 9 = 7875 + * Recommended default TCP_KEEPIDLE(2 hour) + TCP_KEEPINTVL(75 s) * TCP_KEEPCNT(9) 2 * 3600 + 75 * 9 = 7875 */ public static final Duration DEFAULT_TCP_USER_TIMEOUT = Duration.ofSeconds(7875); @@ -531,12 +543,17 @@ private TcpUserTimeoutOptions(TcpUserTimeoutOptions.Builder builder) { this.enabled = builder.enabled; } + /** + * Returns a new {@link TcpUserTimeoutOptions.Builder} to construct {@link TcpUserTimeoutOptions}. + * + * @return a new {@link TcpUserTimeoutOptions.Builder} to construct {@link TcpUserTimeoutOptions}. + */ public static TcpUserTimeoutOptions.Builder builder() { return new TcpUserTimeoutOptions.Builder(); } /** - * Builder class for TcpUserTimeoutOptions. + * Builder class for {@link TcpUserTimeoutOptions}. */ public static class Builder { @@ -547,29 +564,58 @@ public static class Builder { private Builder() { } + /** + * Enable TCP User Timeout. Defaults to disabled. See {@link #DEFAULT_TCP_USER_TIMEOUT_ENABLED}. + * + * @return {@code this} + */ public TcpUserTimeoutOptions.Builder enable() { return enable(true); } + /** + * Disable TCP User Timeout. Defaults to disabled. See {@link #DEFAULT_TCP_USER_TIMEOUT_ENABLED}. + * + * @return {@code this} + */ public TcpUserTimeoutOptions.Builder disable() { return enable(false); } + /** + * Enable or disable TCP User Timeout. Defaults to disabled. See {@link #DEFAULT_TCP_USER_TIMEOUT_ENABLED}. + * + * @param enabled whether to enable TCP User Timeout. + * @return {@code this} + */ public TcpUserTimeoutOptions.Builder enable(boolean enabled) { this.enabled = enabled; return this; } + /** + * The TCP User Timeout. Defaults to {@code 7875 second}. See also {@link #DEFAULT_TCP_USER_TIMEOUT}. + *

+ * The time granularity of is seconds. + * + * @param tcpUserTimeout connection interval time, must be greater {@literal 0} + * @return {@code this} + */ public TcpUserTimeoutOptions.Builder tcpUserTimeout(Duration tcpUserTimeout) { - LettuceAssert.notNull(tcpUserTimeout, "tcpUserTimeout must not be null"); - LettuceAssert.isTrue(!tcpUserTimeout.isNegative(), "tcpUserTimeout must not be begative"); + LettuceAssert.notNull(tcpUserTimeout, "Duration must not be null"); + LettuceAssert.isTrue(!tcpUserTimeout.isNegative(), "Duration must not be negative"); this.tcpUserTimeout = tcpUserTimeout; return this; } + /** + * Create a new instance of {@link TcpUserTimeoutOptions} + * + * @return new instance of {@link TcpUserTimeoutOptions} + */ public TcpUserTimeoutOptions build() { return new TcpUserTimeoutOptions(this); } @@ -577,9 +623,11 @@ public TcpUserTimeoutOptions build() { } /** - * Creates a new Builder instance with the current TcpUserTimeoutOptions state. + * Returns a builder to create new {@link TcpUserTimeoutOptions} whose settings are replicated from the current + * {@link TcpUserTimeoutOptions}. * - * @return a new Builder with the current state + * @return a {@link TcpUserTimeoutOptions.Builder} to create new {@link TcpUserTimeoutOptions} whose settings are + * replicated from the current {@link TcpUserTimeoutOptions} */ public TcpUserTimeoutOptions.Builder mutate() { @@ -591,13 +639,24 @@ public TcpUserTimeoutOptions.Builder mutate() { return builder; } + /** + * Returns whether to enable TCP User Timeout. + * + * @return whether to enable TCP User Timeout + */ public boolean isEnabled() { return enabled; } + /** + * Returns the actual timeout. + * + * @return the actual timeout. + */ public Duration getTcpUserTimeout() { return tcpUserTimeout; } + } }