From 19aa893b55fd8a130945008cbb12a333de7ffb9f Mon Sep 17 00:00:00 2001 From: Thach Le Date: Sat, 26 Apr 2025 18:03:31 +0700 Subject: [PATCH 1/2] Using non-native transports with SocketOptions should cause an error --- src/main/java/io/lettuce/core/SocketOptions.java | 12 +++++++++++- .../java/io/lettuce/core/resource/Transports.java | 9 +++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/lettuce/core/SocketOptions.java b/src/main/java/io/lettuce/core/SocketOptions.java index a69dd4b430..beb7f8d34e 100644 --- a/src/main/java/io/lettuce/core/SocketOptions.java +++ b/src/main/java/io/lettuce/core/SocketOptions.java @@ -19,6 +19,7 @@ */ package io.lettuce.core; +import io.lettuce.core.resource.Transports; import java.time.Duration; import java.util.concurrent.TimeUnit; @@ -228,7 +229,16 @@ public Builder tcpNoDelay(boolean tcpNoDelay) { * @return new instance of {@link SocketOptions} */ public SocketOptions build() { - return new SocketOptions(this); + SocketOptions options = new SocketOptions(this); + + boolean requiresNative = options.isKeepAlive() || options.isExtendedKeepAlive() || options.isEnableTcpUserTimeout(); + + if (requiresNative && !Transports.areNativeTransportsAvailable()) { + throw new IllegalStateException( + "The configured SocketOptions (keepAlive or tcpUserTimeout) require native transports (io_uring, epoll, kqueue), which are not available."); + } + + return options; } } diff --git a/src/main/java/io/lettuce/core/resource/Transports.java b/src/main/java/io/lettuce/core/resource/Transports.java index e36195e4bd..ada0376142 100644 --- a/src/main/java/io/lettuce/core/resource/Transports.java +++ b/src/main/java/io/lettuce/core/resource/Transports.java @@ -42,6 +42,15 @@ public static Class socketChannelClass() { return NioSocketChannel.class; } + /** + * Checks if native transports (io_uring, epoll, kqueue) are available. + * + * @return {@code true} if native transports are available, {@code false} otherwise. + */ + public static boolean areNativeTransportsAvailable() { + return NativeTransports.isAvailable(); + } + /** * @return the default {@link DatagramChannel} for socket (network/UDP) transport. */ From 55c7861be402922695a83a82c90c6fa4fb38fa04 Mon Sep 17 00:00:00 2001 From: Thach Le Date: Mon, 19 May 2025 16:40:49 +0700 Subject: [PATCH 2/2] Add LettuceAssert.assertState Revert previous implement --- .../java/io/lettuce/core/ConnectionBuilder.java | 17 +++++++++++++---- .../java/io/lettuce/core/SocketOptions.java | 12 +----------- .../io/lettuce/core/resource/Transports.java | 9 --------- 3 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/main/java/io/lettuce/core/ConnectionBuilder.java b/src/main/java/io/lettuce/core/ConnectionBuilder.java index 4bb3127b88..acd94b9658 100644 --- a/src/main/java/io/lettuce/core/ConnectionBuilder.java +++ b/src/main/java/io/lettuce/core/ConnectionBuilder.java @@ -276,13 +276,17 @@ public void configureBootstrap(boolean domainSocket, SocketOptions.TcpUserTimeoutOptions tcpUserTimeoutOptions = options.getTcpUserTimeout(); + boolean applied = false; if (IOUringProvider.isAvailable()) { IOUringProvider.applyTcpUserTimeout(bootstrap, tcpUserTimeoutOptions.getTcpUserTimeout()); + applied = true; } 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()); + applied = true; } + + LettuceAssert.assertState(applied, + "TCP User Timeout options could not be applied. Native transports (io_uring or epoll) are required."); } } @@ -291,17 +295,22 @@ public void configureBootstrap(boolean domainSocket, if (options.isKeepAlive() && options.isExtendedKeepAlive()) { SocketOptions.KeepAliveOptions keepAlive = options.getKeepAlive(); + boolean applied = false; if (IOUringProvider.isAvailable()) { IOUringProvider.applyKeepAlive(bootstrap, keepAlive.getCount(), keepAlive.getIdle(), keepAlive.getInterval()); + applied = true; } else if (io.lettuce.core.resource.EpollProvider.isAvailable()) { EpollProvider.applyKeepAlive(bootstrap, keepAlive.getCount(), keepAlive.getIdle(), keepAlive.getInterval()); + applied = true; } else if (ExtendedNioSocketOptions.isAvailable() && !KqueueProvider.isAvailable()) { ExtendedNioSocketOptions.applyKeepAlive(bootstrap, keepAlive.getCount(), keepAlive.getIdle(), keepAlive.getInterval()); - } else { - logger.warn("Cannot apply extended TCP keepalive options to channel type " + channelClass.getName()); + applied = true; } + + LettuceAssert.assertState(applied, + "Extended TCP keepalive options could not be applied. Native transports (io_uring or epoll) or a compatible NIO transport are required."); } } diff --git a/src/main/java/io/lettuce/core/SocketOptions.java b/src/main/java/io/lettuce/core/SocketOptions.java index beb7f8d34e..a69dd4b430 100644 --- a/src/main/java/io/lettuce/core/SocketOptions.java +++ b/src/main/java/io/lettuce/core/SocketOptions.java @@ -19,7 +19,6 @@ */ package io.lettuce.core; -import io.lettuce.core.resource.Transports; import java.time.Duration; import java.util.concurrent.TimeUnit; @@ -229,16 +228,7 @@ public Builder tcpNoDelay(boolean tcpNoDelay) { * @return new instance of {@link SocketOptions} */ public SocketOptions build() { - SocketOptions options = new SocketOptions(this); - - boolean requiresNative = options.isKeepAlive() || options.isExtendedKeepAlive() || options.isEnableTcpUserTimeout(); - - if (requiresNative && !Transports.areNativeTransportsAvailable()) { - throw new IllegalStateException( - "The configured SocketOptions (keepAlive or tcpUserTimeout) require native transports (io_uring, epoll, kqueue), which are not available."); - } - - return options; + return new SocketOptions(this); } } diff --git a/src/main/java/io/lettuce/core/resource/Transports.java b/src/main/java/io/lettuce/core/resource/Transports.java index ada0376142..e36195e4bd 100644 --- a/src/main/java/io/lettuce/core/resource/Transports.java +++ b/src/main/java/io/lettuce/core/resource/Transports.java @@ -42,15 +42,6 @@ public static Class socketChannelClass() { return NioSocketChannel.class; } - /** - * Checks if native transports (io_uring, epoll, kqueue) are available. - * - * @return {@code true} if native transports are available, {@code false} otherwise. - */ - public static boolean areNativeTransportsAvailable() { - return NativeTransports.isAvailable(); - } - /** * @return the default {@link DatagramChannel} for socket (network/UDP) transport. */