From bac59c0e2f626924416114a00dc148f3e55b024b Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 12 Nov 2021 08:51:41 +0100 Subject: [PATCH] Avoid cast to StatefulRedisConnection upon eager LettuceConnectionFactory initialization. We now no longer try to cast the Lettuce connection to StatefulRedisConnection when eagerly initializing the shared connection. Instead, we now introduced another method to obtain the cluster connection. Closes #2186 --- .../lettuce/LettuceConnectionFactory.java | 32 ++++++++++--- .../LettuceConnectionFactoryTests.java | 47 +++++++++++++++++-- 2 files changed, 68 insertions(+), 11 deletions(-) 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 cd2463f80..e95a8c85f 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 @@ -438,9 +438,7 @@ public class LettuceConnectionFactory RedisClusterClient clusterClient = (RedisClusterClient) client; - StatefulRedisClusterConnection sharedConnection = getShareNativeConnection() - ? (StatefulRedisClusterConnection) getOrCreateSharedConnection().getConnection() - : null; + StatefulRedisClusterConnection sharedConnection = getSharedClusterConnection(); LettuceClusterTopologyProvider topologyProvider = new LettuceClusterTopologyProvider(clusterClient); return doCreateLettuceClusterConnection(sharedConnection, connectionProvider, topologyProvider, @@ -540,7 +538,12 @@ public class LettuceConnectionFactory resetConnection(); - getSharedConnection(); + if (isClusterAware()) { + getSharedClusterConnection(); + } else { + getSharedConnection(); + } + getSharedReactiveConnection(); } @@ -1081,12 +1084,27 @@ public class LettuceConnectionFactory } /** - * @return the shared connection using {@literal byte} array encoding for imperative API use. {@literal null} if - * {@link #getShareNativeConnection() connection sharing} is disabled. + * @return the shared connection using {@literal byte[]} encoding for imperative API use. {@literal null} if + * {@link #getShareNativeConnection() connection sharing} is disabled or when connected to Redis Cluster. */ @Nullable protected StatefulRedisConnection getSharedConnection() { - return shareNativeConnection ? (StatefulRedisConnection) getOrCreateSharedConnection().getConnection() : null; + return shareNativeConnection && !isClusterAware() + ? (StatefulRedisConnection) getOrCreateSharedConnection().getConnection() + : null; + } + + /** + * @return the shared cluster connection using {@literal byte[]} encoding for imperative API use. {@literal null} if + * {@link #getShareNativeConnection() connection sharing} is disabled or when connected to Redis + * Standalone/Sentinel/Master-Replica. + * @since 2.5.7 + */ + @Nullable + protected StatefulRedisClusterConnection getSharedClusterConnection() { + return shareNativeConnection && isClusterAware() + ? (StatefulRedisClusterConnection) getOrCreateSharedConnection().getConnection() + : null; } /** diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryTests.java index 9f0518317..6bd0750e6 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryTests.java @@ -48,6 +48,7 @@ import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.RedisStaticMasterReplicaConfiguration; import org.springframework.data.redis.connection.StringRedisConnection; import org.springframework.data.redis.connection.lettuce.extension.LettuceConnectionFactoryExtension; +import org.springframework.data.redis.test.condition.EnabledOnRedisClusterAvailable; import org.springframework.data.redis.test.extension.LettuceTestClientResources; /** @@ -85,7 +86,6 @@ class LettuceConnectionFactoryTests { factory.destroy(); } - @SuppressWarnings("rawtypes") @Test void testGetNewConnectionOnError() throws Exception { @@ -462,9 +462,8 @@ class LettuceConnectionFactoryTests { RedisConnection connection = factory.getConnection(); - assertThatThrownBy(() -> connection.pSubscribe((message, pattern) -> { - }, "foo".getBytes())).isInstanceOf(RedisConnectionFailureException.class) - .hasCauseInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> connection.pSubscribe((message, pattern) -> {}, "foo".getBytes())) + .isInstanceOf(RedisConnectionFailureException.class).hasCauseInstanceOf(UnsupportedOperationException.class); connection.close(); factory.destroy(); @@ -558,4 +557,44 @@ class LettuceConnectionFactoryTests { connection.close(); } + + @Test // GH-2186 + void shouldInitializeMasterReplicaConnectionsEagerly() { + + LettuceClientConfiguration configuration = LettuceClientConfiguration.builder() + .clientResources(LettuceTestClientResources.getSharedClientResources()).build(); + + RedisStaticMasterReplicaConfiguration elastiCache = new RedisStaticMasterReplicaConfiguration( + SettingsUtils.getHost()).node(SettingsUtils.getHost(), SettingsUtils.getPort() + 1); + + LettuceConnectionFactory factory = new LettuceConnectionFactory(elastiCache, configuration); + factory.setEagerInitialization(true); + factory.afterPropertiesSet(); + + assertThat(factory.getSharedConnection()).isNotNull(); + assertThat(factory.getSharedClusterConnection()).isNull(); + + factory.getConnection().close(); + factory.destroy(); + } + + @Test // GH-2186 + @EnabledOnRedisClusterAvailable + void shouldInitializeClusterConnectionsEagerly() { + + LettuceClientConfiguration configuration = LettuceClientConfiguration.builder() + .clientResources(LettuceTestClientResources.getSharedClientResources()).build(); + + LettuceConnectionFactory factory = new LettuceConnectionFactory(SettingsUtils.clusterConfiguration(), + configuration); + factory.setEagerInitialization(true); + factory.afterPropertiesSet(); + + assertThat(factory.getSharedConnection()).isNull(); + assertThat(factory.getSharedClusterConnection()).isNotNull(); + + factory.getConnection().close(); + factory.destroy(); + } + }