From baf3c8b98425d732521278acbe8d1ae68da60339 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Mon, 8 Apr 2024 19:40:33 -0700 Subject: [PATCH 1/8] Add `SMOVE` command. (#182) * Add `SMOVE` command. Signed-off-by: Yury-Fridlyand * Update javadoc. Signed-off-by: Yury-Fridlyand * Update javadoc. Signed-off-by: Yury-Fridlyand * PR comments. Signed-off-by: Yury-Fridlyand * PR comments. Signed-off-by: Yury-Fridlyand --------- Signed-off-by: Yury-Fridlyand --- glide-core/src/client/value_conversion.rs | 11 ++++- glide-core/src/protobuf/redis_request.proto | 1 + glide-core/src/socket_listener.rs | 1 + .../src/main/java/glide/api/BaseClient.java | 8 ++++ .../glide/api/commands/SetBaseCommands.java | 18 ++++++++ .../glide/api/models/BaseTransaction.java | 18 ++++++++ .../test/java/glide/api/RedisClientTest.java | 26 +++++++++++ .../glide/api/models/TransactionTests.java | 6 +++ .../test/java/glide/SharedCommandTests.java | 46 +++++++++++++++++++ .../java/glide/TransactionTestUtilities.java | 3 ++ 10 files changed, 137 insertions(+), 1 deletion(-) diff --git a/glide-core/src/client/value_conversion.rs b/glide-core/src/client/value_conversion.rs index 84a6626efa..e79979a40c 100644 --- a/glide-core/src/client/value_conversion.rs +++ b/glide-core/src/client/value_conversion.rs @@ -213,13 +213,14 @@ fn convert_array_to_map( pub(crate) fn expected_type_for_cmd(cmd: &Cmd) -> Option { let command = cmd.command()?; + // TODO use enum to avoid mistakes match command.as_slice() { b"HGETALL" | b"XREAD" | b"CONFIG GET" | b"FT.CONFIG GET" | b"HELLO" => { Some(ExpectedReturnType::Map) } b"INCRBYFLOAT" | b"HINCRBYFLOAT" => Some(ExpectedReturnType::Double), b"HEXISTS" | b"HSETNX" | b"EXPIRE" | b"EXPIREAT" | b"PEXPIRE" | b"PEXPIREAT" - | b"SISMEMBER" | b"PERSIST" => Some(ExpectedReturnType::Boolean), + | b"SISMEMBER" | b"PERSIST" | b"SMOVE" => Some(ExpectedReturnType::Boolean), b"SMEMBERS" => Some(ExpectedReturnType::Set), b"ZSCORE" => Some(ExpectedReturnType::DoubleOrNull), b"ZPOPMIN" | b"ZPOPMAX" => Some(ExpectedReturnType::MapOfStringToDouble), @@ -318,6 +319,14 @@ mod tests { assert!(expected_type_for_cmd(redis::cmd("ZREVRANK").arg("key").arg("member")).is_none()); } + #[test] + fn convert_smove_to_bool() { + assert!(matches!( + expected_type_for_cmd(redis::cmd("SMOVE").arg("key1").arg("key2").arg("elem")), + Some(ExpectedReturnType::Boolean) + )); + } + #[test] fn test_convert_to_map_of_string_to_double() { assert_eq!( diff --git a/glide-core/src/protobuf/redis_request.proto b/glide-core/src/protobuf/redis_request.proto index 327b9fa335..f4dcd3b42e 100644 --- a/glide-core/src/protobuf/redis_request.proto +++ b/glide-core/src/protobuf/redis_request.proto @@ -135,6 +135,7 @@ enum RequestType { Rename = 91; DBSize = 92; Brpop = 93; + SMove = 106; } message Command { diff --git a/glide-core/src/socket_listener.rs b/glide-core/src/socket_listener.rs index 10d1935200..9999278680 100644 --- a/glide-core/src/socket_listener.rs +++ b/glide-core/src/socket_listener.rs @@ -362,6 +362,7 @@ fn get_command(request: &Command) -> Option { RequestType::Rename => Some(cmd("RENAME")), RequestType::DBSize => Some(cmd("DBSIZE")), RequestType::Brpop => Some(cmd("BRPOP")), + RequestType::SMove => Some(cmd("SMOVE")), } } diff --git a/java/client/src/main/java/glide/api/BaseClient.java b/java/client/src/main/java/glide/api/BaseClient.java index fdc99cc981..82519168bb 100644 --- a/java/client/src/main/java/glide/api/BaseClient.java +++ b/java/client/src/main/java/glide/api/BaseClient.java @@ -41,6 +41,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.SAdd; import static redis_request.RedisRequestOuterClass.RequestType.SCard; import static redis_request.RedisRequestOuterClass.RequestType.SMembers; +import static redis_request.RedisRequestOuterClass.RequestType.SMove; import static redis_request.RedisRequestOuterClass.RequestType.SRem; import static redis_request.RedisRequestOuterClass.RequestType.SetString; import static redis_request.RedisRequestOuterClass.RequestType.Strlen; @@ -460,6 +461,13 @@ public CompletableFuture scard(@NonNull String key) { return commandManager.submitNewCommand(SCard, new String[] {key}, this::handleLongResponse); } + @Override + public CompletableFuture smove( + @NonNull String source, @NonNull String destination, @NonNull String member) { + return commandManager.submitNewCommand( + SMove, new String[] {source, destination, member}, this::handleBooleanResponse); + } + @Override public CompletableFuture exists(@NonNull String[] keys) { return commandManager.submitNewCommand(Exists, keys, this::handleLongResponse); diff --git a/java/client/src/main/java/glide/api/commands/SetBaseCommands.java b/java/client/src/main/java/glide/api/commands/SetBaseCommands.java index f84f01ca96..71dbcd23c0 100644 --- a/java/client/src/main/java/glide/api/commands/SetBaseCommands.java +++ b/java/client/src/main/java/glide/api/commands/SetBaseCommands.java @@ -75,4 +75,22 @@ public interface SetBaseCommands { * } */ CompletableFuture scard(String key); + + /** + * Moves a set element from one set to another. Creates a new destination set if needed.
+ * The operation is atomic. + * + * @see redis.io for details. + * @param source The key of the set to remove the element from. + * @param destination The key of the set to add the element to. + * @param member The set element to move. + * @return true on success, or false if the source set does + * not exist or the element is not a member of the source set. + * @example + *
{@code
+     * boolean moved = client.smove("set1", "set2", "element").get();
+     * assert moved;
+     * }
+ */ + CompletableFuture smove(String source, String destination, String member); } diff --git a/java/client/src/main/java/glide/api/models/BaseTransaction.java b/java/client/src/main/java/glide/api/models/BaseTransaction.java index d50210fcb4..3fd7490b3e 100644 --- a/java/client/src/main/java/glide/api/models/BaseTransaction.java +++ b/java/client/src/main/java/glide/api/models/BaseTransaction.java @@ -49,6 +49,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.SAdd; import static redis_request.RedisRequestOuterClass.RequestType.SCard; import static redis_request.RedisRequestOuterClass.RequestType.SMembers; +import static redis_request.RedisRequestOuterClass.RequestType.SMove; import static redis_request.RedisRequestOuterClass.RequestType.SRem; import static redis_request.RedisRequestOuterClass.RequestType.SetString; import static redis_request.RedisRequestOuterClass.RequestType.Strlen; @@ -789,6 +790,23 @@ public T scard(@NonNull String key) { return getThis(); } + /** + * Moves a set element from one set to another. Creates a new destination set if needed.
+ * The operation is atomic. + * + * @see redis.io for details. + * @param source The key of the set to remove the element from. + * @param destination The key of the set to add the element to. + * @param member The set element to move. + * @return Command response - true on success, or false if the + * source set does not exist or the element is not a member of the source set. + */ + public T smove(@NonNull String source, @NonNull String destination, @NonNull String member) { + ArgsArray commandArgs = buildArgs(source, destination, member); + protobufTransaction.addCommands(buildCommand(SMove, commandArgs)); + return getThis(); + } + /** * Reads the configuration parameters of a running Redis server. * diff --git a/java/client/src/test/java/glide/api/RedisClientTest.java b/java/client/src/test/java/glide/api/RedisClientTest.java index a17615d1ac..19b497555e 100644 --- a/java/client/src/test/java/glide/api/RedisClientTest.java +++ b/java/client/src/test/java/glide/api/RedisClientTest.java @@ -11,6 +11,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -60,6 +61,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.SAdd; import static redis_request.RedisRequestOuterClass.RequestType.SCard; import static redis_request.RedisRequestOuterClass.RequestType.SMembers; +import static redis_request.RedisRequestOuterClass.RequestType.SMove; import static redis_request.RedisRequestOuterClass.RequestType.SRem; import static redis_request.RedisRequestOuterClass.RequestType.Select; import static redis_request.RedisRequestOuterClass.RequestType.SetString; @@ -1480,6 +1482,30 @@ public void scard_returns_success() { assertEquals(value, payload); } + @SneakyThrows + @Test + public void smove_returns_success() { + // setup + String source = "src"; + String destination = "dst"; + String member = "elem"; + String[] arguments = {source, destination, member}; + + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(true); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(SMove), eq(arguments), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.smove(source, destination, member); + + // verify + assertEquals(testResponse, response); + assertTrue(response.get()); + } + @SneakyThrows @Test public void zadd_noOptions_returns_success() { diff --git a/java/client/src/test/java/glide/api/models/TransactionTests.java b/java/client/src/test/java/glide/api/models/TransactionTests.java index 99c5e065d8..2dcf828b0f 100644 --- a/java/client/src/test/java/glide/api/models/TransactionTests.java +++ b/java/client/src/test/java/glide/api/models/TransactionTests.java @@ -47,6 +47,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.SAdd; import static redis_request.RedisRequestOuterClass.RequestType.SCard; import static redis_request.RedisRequestOuterClass.RequestType.SMembers; +import static redis_request.RedisRequestOuterClass.RequestType.SMove; import static redis_request.RedisRequestOuterClass.RequestType.SRem; import static redis_request.RedisRequestOuterClass.RequestType.SetString; import static redis_request.RedisRequestOuterClass.RequestType.Strlen; @@ -232,6 +233,11 @@ public void transaction_builds_protobuf_request(BaseTransaction transaction) transaction.scard("key"); results.add(Pair.of(SCard, ArgsArray.newBuilder().addArgs("key").build())); + transaction.smove("key1", "key2", "elem"); + results.add( + Pair.of( + SMove, ArgsArray.newBuilder().addArgs("key1").addArgs("key2").addArgs("elem").build())); + transaction.exists(new String[] {"key1", "key2"}); results.add(Pair.of(Exists, ArgsArray.newBuilder().addArgs("key1").addArgs("key2").build())); diff --git a/java/integTest/src/test/java/glide/SharedCommandTests.java b/java/integTest/src/test/java/glide/SharedCommandTests.java index a7ddbe0dc9..e3cc69c4e4 100644 --- a/java/integTest/src/test/java/glide/SharedCommandTests.java +++ b/java/integTest/src/test/java/glide/SharedCommandTests.java @@ -744,6 +744,52 @@ public void sadd_srem_scard_smembers_key_with_non_set_value(BaseClient client) { assertTrue(e.getCause() instanceof RequestException); } + @SneakyThrows + @ParameterizedTest + @MethodSource("getClients") + public void smove(BaseClient client) { + String setKey1 = "{key}" + UUID.randomUUID(); + String setKey2 = "{key}" + UUID.randomUUID(); + String setKey3 = "{key}" + UUID.randomUUID(); + String nonSetKey = "{key}" + UUID.randomUUID(); + + assertEquals(3, client.sadd(setKey1, new String[] {"1", "2", "3"}).get()); + assertEquals(2, client.sadd(setKey2, new String[] {"2", "3"}).get()); + // move an elem + assertTrue(client.smove(setKey1, setKey2, "1").get()); + assertEquals(Set.of("2", "3"), client.smembers(setKey1).get()); + assertEquals(Set.of("1", "2", "3"), client.smembers(setKey2).get()); + // move an elem which preset at destination + assertTrue(client.smove(setKey2, setKey1, "2").get()); + assertEquals(Set.of("2", "3"), client.smembers(setKey1).get()); + assertEquals(Set.of("1", "3"), client.smembers(setKey2).get()); + // move from missing key + assertFalse(client.smove(setKey3, setKey1, "4").get()); + assertEquals(Set.of("2", "3"), client.smembers(setKey1).get()); + // move to a new set + assertTrue(client.smove(setKey1, setKey3, "2").get()); + assertEquals(Set.of("3"), client.smembers(setKey1).get()); + assertEquals(Set.of("2"), client.smembers(setKey3).get()); + // move missing element + assertFalse(client.smove(setKey1, setKey3, "42").get()); + assertEquals(Set.of("3"), client.smembers(setKey1).get()); + assertEquals(Set.of("2"), client.smembers(setKey3).get()); + // move missing element to missing key + assertFalse(client.smove(setKey1, nonSetKey, "42").get()); + assertEquals(Set.of("3"), client.smembers(setKey1).get()); + assertEquals("none", client.type(nonSetKey).get()); + + // Key exists, but it is not a set + assertEquals(OK, client.set(nonSetKey, "bar").get()); + ExecutionException executionException = + assertThrows(ExecutionException.class, () -> client.smove(nonSetKey, setKey1, "_").get()); + assertTrue(executionException.getCause() instanceof RequestException); + + executionException = + assertThrows(ExecutionException.class, () -> client.smove(setKey1, nonSetKey, "_").get()); + assertTrue(executionException.getCause() instanceof RequestException); + } + @SneakyThrows @ParameterizedTest @MethodSource("getClients") diff --git a/java/integTest/src/test/java/glide/TransactionTestUtilities.java b/java/integTest/src/test/java/glide/TransactionTestUtilities.java index 5af67f20b5..ecfc1cd084 100644 --- a/java/integTest/src/test/java/glide/TransactionTestUtilities.java +++ b/java/integTest/src/test/java/glide/TransactionTestUtilities.java @@ -17,6 +17,7 @@ public class TransactionTestUtilities { private static final String key5 = "{key}" + UUID.randomUUID(); private static final String key6 = "{key}" + UUID.randomUUID(); private static final String key7 = "{key}" + UUID.randomUUID(); + private static final String setKey2 = "{key}" + UUID.randomUUID(); private static final String key8 = "{key}" + UUID.randomUUID(); private static final String value1 = UUID.randomUUID().toString(); private static final String value2 = UUID.randomUUID().toString(); @@ -83,6 +84,7 @@ public static BaseTransaction transactionTest(BaseTransaction baseTransact baseTransaction.srem(key7, new String[] {"foo"}); baseTransaction.scard(key7); baseTransaction.smembers(key7); + baseTransaction.smove(key7, setKey2, "baz"); baseTransaction.zadd(key8, Map.of("one", 1.0, "two", 2.0, "three", 3.0)); baseTransaction.zaddIncr(key8, "one", 3); @@ -146,6 +148,7 @@ public static Object[] transactionTestResult() { 1L, 1L, Set.of("baz"), + true, // smove(key7, setKey2, "baz") 3L, 4.0, 1L, From bd7df3e5685c1e5fd0f4a5aeeabf17ae9ea3ded0 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Tue, 9 Apr 2024 09:54:02 -0700 Subject: [PATCH 2/8] PR comments. Signed-off-by: Yury-Fridlyand --- .../src/main/java/glide/api/commands/SetBaseCommands.java | 5 +++-- .../src/main/java/glide/api/models/BaseTransaction.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/java/client/src/main/java/glide/api/commands/SetBaseCommands.java b/java/client/src/main/java/glide/api/commands/SetBaseCommands.java index 012d3e91e0..5ebccd7b93 100644 --- a/java/client/src/main/java/glide/api/commands/SetBaseCommands.java +++ b/java/client/src/main/java/glide/api/commands/SetBaseCommands.java @@ -77,8 +77,9 @@ public interface SetBaseCommands { CompletableFuture scard(String key); /** - * Moves a set element from one set to another. Creates a new destination set if needed.
- * The operation is atomic. + * Moves member from the set at source to the set at destination + * , removing it from the source set. Creates a new destination set if needed. The + * operation is atomic. * * @see redis.io for details. * @param source The key of the set to remove the element from. diff --git a/java/client/src/main/java/glide/api/models/BaseTransaction.java b/java/client/src/main/java/glide/api/models/BaseTransaction.java index 3530189f09..af53d69545 100644 --- a/java/client/src/main/java/glide/api/models/BaseTransaction.java +++ b/java/client/src/main/java/glide/api/models/BaseTransaction.java @@ -880,8 +880,9 @@ public T scard(@NonNull String key) { } /** - * Moves a set element from one set to another. Creates a new destination set if needed.
- * The operation is atomic. + * Moves member from the set at source to the set at destination + * , removing it from the source set. Creates a new destination set if needed. The + * operation is atomic. * * @see redis.io for details. * @param source The key of the set to remove the element from. From 8349d1f985639d3d5150de656b207d7d4062c255 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Tue, 9 Apr 2024 19:03:47 -0700 Subject: [PATCH 3/8] PR comments. Signed-off-by: Yury-Fridlyand --- java/integTest/src/test/java/glide/SharedCommandTests.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/java/integTest/src/test/java/glide/SharedCommandTests.java b/java/integTest/src/test/java/glide/SharedCommandTests.java index b89692561f..200df62d53 100644 --- a/java/integTest/src/test/java/glide/SharedCommandTests.java +++ b/java/integTest/src/test/java/glide/SharedCommandTests.java @@ -835,25 +835,31 @@ public void smove(BaseClient client) { assertEquals(3, client.sadd(setKey1, new String[] {"1", "2", "3"}).get()); assertEquals(2, client.sadd(setKey2, new String[] {"2", "3"}).get()); + // move an elem assertTrue(client.smove(setKey1, setKey2, "1").get()); assertEquals(Set.of("2", "3"), client.smembers(setKey1).get()); assertEquals(Set.of("1", "2", "3"), client.smembers(setKey2).get()); + // move an elem which preset at destination assertTrue(client.smove(setKey2, setKey1, "2").get()); assertEquals(Set.of("2", "3"), client.smembers(setKey1).get()); assertEquals(Set.of("1", "3"), client.smembers(setKey2).get()); + // move from missing key assertFalse(client.smove(setKey3, setKey1, "4").get()); assertEquals(Set.of("2", "3"), client.smembers(setKey1).get()); + // move to a new set assertTrue(client.smove(setKey1, setKey3, "2").get()); assertEquals(Set.of("3"), client.smembers(setKey1).get()); assertEquals(Set.of("2"), client.smembers(setKey3).get()); + // move missing element assertFalse(client.smove(setKey1, setKey3, "42").get()); assertEquals(Set.of("3"), client.smembers(setKey1).get()); assertEquals(Set.of("2"), client.smembers(setKey3).get()); + // move missing element to missing key assertFalse(client.smove(setKey1, nonSetKey, "42").get()); assertEquals(Set.of("3"), client.smembers(setKey1).get()); From 88534bd87dae8e04a2151f6cff9267104aaeab8a Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Tue, 9 Apr 2024 19:29:18 -0700 Subject: [PATCH 4/8] Typo fix. Signed-off-by: Yury-Fridlyand --- java/integTest/src/test/java/glide/SharedCommandTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/integTest/src/test/java/glide/SharedCommandTests.java b/java/integTest/src/test/java/glide/SharedCommandTests.java index 200df62d53..9470cef7cb 100644 --- a/java/integTest/src/test/java/glide/SharedCommandTests.java +++ b/java/integTest/src/test/java/glide/SharedCommandTests.java @@ -859,7 +859,7 @@ public void smove(BaseClient client) { assertFalse(client.smove(setKey1, setKey3, "42").get()); assertEquals(Set.of("3"), client.smembers(setKey1).get()); assertEquals(Set.of("2"), client.smembers(setKey3).get()); - + // move missing element to missing key assertFalse(client.smove(setKey1, nonSetKey, "42").get()); assertEquals(Set.of("3"), client.smembers(setKey1).get()); From 80bfcfa3279138658dc44e1349df882937a1c148 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Wed, 10 Apr 2024 14:21:11 -0700 Subject: [PATCH 5/8] Update UT. Signed-off-by: Yury-Fridlyand --- .../src/test/java/glide/api/models/TransactionTests.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/java/client/src/test/java/glide/api/models/TransactionTests.java b/java/client/src/test/java/glide/api/models/TransactionTests.java index d9b34e40b4..33889b255e 100644 --- a/java/client/src/test/java/glide/api/models/TransactionTests.java +++ b/java/client/src/test/java/glide/api/models/TransactionTests.java @@ -251,9 +251,7 @@ public void transaction_builds_protobuf_request(BaseTransaction transaction) results.add(Pair.of(SCard, buildArgs("key"))); transaction.smove("key1", "key2", "elem"); - results.add( - Pair.of( - SMove, ArgsArray.newBuilder().addArgs("key1").addArgs("key2").addArgs("elem").build())); + results.add(Pair.of(SMove, buildArgs("key1", "key2", "elem"))); transaction.exists(new String[] {"key1", "key2"}); results.add(Pair.of(Exists, buildArgs("key1", "key2"))); From 4d9746de5195d63052459de8e0a2f64b45a1ec95 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Tue, 16 Apr 2024 15:10:24 -0700 Subject: [PATCH 6/8] PR comments. Signed-off-by: Yury-Fridlyand --- .../java/glide/api/commands/SetBaseCommands.java | 6 ++++-- .../src/test/java/glide/SharedCommandTests.java | 13 +++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/java/client/src/main/java/glide/api/commands/SetBaseCommands.java b/java/client/src/main/java/glide/api/commands/SetBaseCommands.java index 0d21949998..94ce1ec7ce 100644 --- a/java/client/src/main/java/glide/api/commands/SetBaseCommands.java +++ b/java/client/src/main/java/glide/api/commands/SetBaseCommands.java @@ -79,7 +79,9 @@ public interface SetBaseCommands { /** * Moves member from the set at source to the set at destination * , removing it from the source set. Creates a new destination set if needed. The - * operation is atomic. + * operation is atomic.
+ * When in cluster mode, source and destination must map to the same + * hash slot. * * @see redis.io for details. * @param source The key of the set to remove the element from. @@ -89,7 +91,7 @@ public interface SetBaseCommands { * not exist or the element is not a member of the source set. * @example *
{@code
-     * boolean moved = client.smove("set1", "set2", "element").get();
+     * Boolean moved = client.smove("set1", "set2", "element").get();
      * assert moved;
      * }
*/ diff --git a/java/integTest/src/test/java/glide/SharedCommandTests.java b/java/integTest/src/test/java/glide/SharedCommandTests.java index 0481418e71..6ea776dee3 100644 --- a/java/integTest/src/test/java/glide/SharedCommandTests.java +++ b/java/integTest/src/test/java/glide/SharedCommandTests.java @@ -15,6 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -959,11 +960,19 @@ public void smove(BaseClient client) { assertEquals(OK, client.set(nonSetKey, "bar").get()); ExecutionException executionException = assertThrows(ExecutionException.class, () -> client.smove(nonSetKey, setKey1, "_").get()); - assertTrue(executionException.getCause() instanceof RequestException); + assertInstanceOf(RequestException.class, executionException.getCause()); executionException = assertThrows(ExecutionException.class, () -> client.smove(setKey1, nonSetKey, "_").get()); - assertTrue(executionException.getCause() instanceof RequestException); + assertInstanceOf(RequestException.class, executionException.getCause()); + + // same-slot requirement + if (client instanceof RedisClusterClient) { + executionException = + assertThrows(ExecutionException.class, () -> client.smove("abc", "zxy", "lkn").get()); + assertInstanceOf(RequestException.class, executionException.getCause()); + assertTrue(executionException.getMessage().toLowerCase().contains("crossslot")); + } } @SneakyThrows From 2b53179739e0ff67661d224ec0afabf9dbc6e4dd Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Tue, 16 Apr 2024 15:13:53 -0700 Subject: [PATCH 7/8] update doc. Signed-off-by: Yury-Fridlyand --- .../src/main/java/glide/api/commands/SetBaseCommands.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/client/src/main/java/glide/api/commands/SetBaseCommands.java b/java/client/src/main/java/glide/api/commands/SetBaseCommands.java index 94ce1ec7ce..ba2666a0fd 100644 --- a/java/client/src/main/java/glide/api/commands/SetBaseCommands.java +++ b/java/client/src/main/java/glide/api/commands/SetBaseCommands.java @@ -80,9 +80,9 @@ public interface SetBaseCommands { * Moves member from the set at source to the set at destination * , removing it from the source set. Creates a new destination set if needed. The * operation is atomic.
- * When in cluster mode, source and destination must map to the same - * hash slot. * + * @apiNote When in cluster mode, source and destination must map to the + * same hash slot. * @see redis.io for details. * @param source The key of the set to remove the element from. * @param destination The key of the set to add the element to. From 33e120560f898a613963a628cbf9f60a0da62dc8 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Tue, 16 Apr 2024 15:17:09 -0700 Subject: [PATCH 8/8] update doc. Signed-off-by: Yury-Fridlyand --- .../src/main/java/glide/api/commands/SetBaseCommands.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/client/src/main/java/glide/api/commands/SetBaseCommands.java b/java/client/src/main/java/glide/api/commands/SetBaseCommands.java index ba2666a0fd..b5d54ded84 100644 --- a/java/client/src/main/java/glide/api/commands/SetBaseCommands.java +++ b/java/client/src/main/java/glide/api/commands/SetBaseCommands.java @@ -79,7 +79,7 @@ public interface SetBaseCommands { /** * Moves member from the set at source to the set at destination * , removing it from the source set. Creates a new destination set if needed. The - * operation is atomic.
+ * operation is atomic. * * @apiNote When in cluster mode, source and destination must map to the * same hash slot.