Use Lettuce functionality for Cluster commands where possible.

We now remove our own code in favor of Lettuce's advanced cluster support to leverage asynchronous functionality in pipelining.

Document pipelining restrictions regarding Redis Cluster.

Original Pull Request: #2889
This commit is contained in:
Mark Paluch
2024-04-04 09:23:23 +02:00
committed by Christoph Strobl
parent d785b5f870
commit 6f28b530b0
9 changed files with 70 additions and 190 deletions

View File

@@ -1620,7 +1620,15 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
nativeConnection.set(KEY_1, VALUE_1);
nativeConnection.set(KEY_2, VALUE_2);
assertThat(clusterConnection.randomKey()).isNotNull();
for (int i = 0; i < 20; i++) {
byte[] k = clusterConnection.randomKey();
if (k == null) {
continue;
}
assertThat(k).isIn(KEY_1_BYTES, KEY_2_BYTES);
}
}
@Test // DATAREDIS-315

View File

@@ -18,7 +18,6 @@ package org.springframework.data.redis.connection.lettuce;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import static org.springframework.data.redis.connection.ClusterTestVariables.*;
import static org.springframework.data.redis.test.util.MockitoUtils.*;
import io.lettuce.core.RedisFuture;
import io.lettuce.core.RedisURI;
@@ -46,6 +45,7 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.springframework.data.redis.connection.ClusterCommandExecutor;
import org.springframework.data.redis.connection.ClusterNodeResourceProvider;
import org.springframework.data.redis.connection.ClusterTopologyProvider;
@@ -193,22 +193,6 @@ class LettuceClusterConnectionUnitTests {
assertThat(connection.isClosed()).isTrue();
}
@Test // DATAREDIS-315
void keysShouldBeRunOnAllClusterNodes() {
when(clusterConnection1Mock.keys(any(byte[].class))).thenReturn(Collections.<byte[]> emptyList());
when(clusterConnection2Mock.keys(any(byte[].class))).thenReturn(Collections.<byte[]> emptyList());
when(clusterConnection3Mock.keys(any(byte[].class))).thenReturn(Collections.<byte[]> emptyList());
byte[] pattern = LettuceConverters.toBytes("*");
connection.keys(pattern);
verify(clusterConnection1Mock, times(1)).keys(pattern);
verify(clusterConnection2Mock, times(1)).keys(pattern);
verify(clusterConnection3Mock, times(1)).keys(pattern);
}
@Test // DATAREDIS-315
void keysShouldOnlyBeRunOnDedicatedNodeWhenPinned() {
@@ -223,38 +207,6 @@ class LettuceClusterConnectionUnitTests {
verify(clusterConnection3Mock, never()).keys(pattern);
}
@Test // DATAREDIS-315
void randomKeyShouldReturnAnyKeyFromRandomNode() {
when(clusterConnection1Mock.randomkey()).thenReturn(KEY_1_BYTES);
when(clusterConnection2Mock.randomkey()).thenReturn(KEY_2_BYTES);
when(clusterConnection3Mock.randomkey()).thenReturn(KEY_3_BYTES);
assertThat(connection.randomKey()).isIn(KEY_1_BYTES, KEY_2_BYTES, KEY_3_BYTES);
verifyInvocationsAcross("randomkey", times(1), clusterConnection1Mock, clusterConnection2Mock,
clusterConnection3Mock);
}
@Test // DATAREDIS-315
void randomKeyShouldReturnKeyWhenAvailableOnAnyNode() {
when(clusterConnection3Mock.randomkey()).thenReturn(KEY_3_BYTES);
for (int i = 0; i < 100; i++) {
assertThat(connection.randomKey()).isEqualTo(KEY_3_BYTES);
}
}
@Test // DATAREDIS-315
void randomKeyShouldReturnNullWhenNoKeysPresentOnAllNodes() {
when(clusterConnection1Mock.randomkey()).thenReturn(null);
when(clusterConnection2Mock.randomkey()).thenReturn(null);
when(clusterConnection3Mock.randomkey()).thenReturn(null);
assertThat(connection.randomKey()).isNull();
}
@Test // DATAREDIS-315
void clusterSetSlotImportingShouldBeExecutedCorrectly() {

View File

@@ -361,8 +361,7 @@ public class RedisTemplateIntegrationTests<K, V> {
try {
// Await EXEC completion as it's executed on a dedicated connection.
Thread.sleep(100);
} catch (InterruptedException ignore) {
}
} catch (InterruptedException ignore) {}
operations.opsForValue().set(key1, value1);
operations.opsForValue().get(key1);
@@ -673,7 +672,16 @@ public class RedisTemplateIntegrationTests<K, V> {
K key1 = keyFactory.instance();
V value1 = valueFactory.instance();
redisTemplate.opsForValue().set(key1, value1);
assertThat(redisTemplate.randomKey()).isEqualTo(key1);
for (int i = 0; i < 20; i++) {
K k = redisTemplate.randomKey();
if (k == null) {
continue;
}
assertThat(k).isEqualTo(key1);
}
}
@ParameterizedRedisTest
@@ -723,8 +731,7 @@ public class RedisTemplateIntegrationTests<K, V> {
th.start();
try {
th.join();
} catch (InterruptedException ignore) {
}
} catch (InterruptedException ignore) {}
operations.multi();
operations.opsForValue().set(key1, value3);
@@ -756,8 +763,7 @@ public class RedisTemplateIntegrationTests<K, V> {
th.start();
try {
th.join();
} catch (InterruptedException ignore) {
}
} catch (InterruptedException ignore) {}
operations.unwatch();
operations.multi();
@@ -794,8 +800,7 @@ public class RedisTemplateIntegrationTests<K, V> {
th.start();
try {
th.join();
} catch (InterruptedException ignore) {
}
} catch (InterruptedException ignore) {}
operations.multi();
operations.opsForValue().set(key1, value3);