From 4ce976c9efe9da9845ff3fe08ae6ebf36c5bf521 Mon Sep 17 00:00:00 2001 From: SanHalacogluImproving <144171266+SanHalacogluImproving@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:36:56 -0700 Subject: [PATCH] Java: Add `Zmscore` command. (Sorted Set Command Group) (#1234) * Java: Add Zmscore command. (Sorted Set Command Group) (#173) * Minor update + remove change log. * Minor documentation update. * Minor IT update. * Rebase + Spotless. * Minor IT test update. --- glide-core/src/protobuf/redis_request.proto | 3 ++- glide-core/src/request_type.rs | 3 +++ .../src/main/java/glide/api/BaseClient.java | 10 +++++++ .../api/commands/SortedSetBaseCommands.java | 18 +++++++++++++ .../glide/api/models/BaseTransaction.java | 18 +++++++++++++ .../test/java/glide/api/RedisClientTest.java | 26 ++++++++++++++++++ .../glide/api/models/TransactionTests.java | 7 +++++ .../test/java/glide/SharedCommandTests.java | 27 +++++++++++++++++++ .../java/glide/TransactionTestUtilities.java | 2 ++ 9 files changed, 113 insertions(+), 1 deletion(-) diff --git a/glide-core/src/protobuf/redis_request.proto b/glide-core/src/protobuf/redis_request.proto index 08428b92ea..61f0747bd2 100644 --- a/glide-core/src/protobuf/redis_request.proto +++ b/glide-core/src/protobuf/redis_request.proto @@ -143,6 +143,7 @@ enum RequestType { Blpop = 100; RPushX = 102; LPushX = 103; + ZMScore = 104; } message Command { @@ -169,7 +170,7 @@ message Transaction { message RedisRequest { uint32 callback_idx = 1; - + oneof command { Command single_command = 2; Transaction transaction = 3; diff --git a/glide-core/src/request_type.rs b/glide-core/src/request_type.rs index ffed834871..41138cadaf 100644 --- a/glide-core/src/request_type.rs +++ b/glide-core/src/request_type.rs @@ -111,6 +111,7 @@ pub enum RequestType { Blpop = 100, RPushX = 102, LPushX = 103, + ZMScore = 104, } fn get_two_word_command(first: &str, second: &str) -> Cmd { @@ -225,6 +226,7 @@ impl From<::protobuf::EnumOrUnknown> for RequestType { ProtobufRequestType::LPushX => RequestType::LPushX, ProtobufRequestType::Blpop => RequestType::Blpop, ProtobufRequestType::Spop => RequestType::Spop, + ProtobufRequestType::ZMScore => RequestType::ZMScore, } } } @@ -335,6 +337,7 @@ impl RequestType { RequestType::LPushX => Some(cmd("LPUSHX")), RequestType::Blpop => Some(cmd("BLPOP")), RequestType::Spop => Some(cmd("SPOP")), + RequestType::ZMScore => Some(cmd("ZMSCORE")), } } } diff --git a/java/client/src/main/java/glide/api/BaseClient.java b/java/client/src/main/java/glide/api/BaseClient.java index 6422a66a0a..bf29fb4389 100644 --- a/java/client/src/main/java/glide/api/BaseClient.java +++ b/java/client/src/main/java/glide/api/BaseClient.java @@ -60,6 +60,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.Type; import static redis_request.RedisRequestOuterClass.RequestType.Unlink; import static redis_request.RedisRequestOuterClass.RequestType.XAdd; +import static redis_request.RedisRequestOuterClass.RequestType.ZMScore; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMax; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMin; import static redis_request.RedisRequestOuterClass.RequestType.ZScore; @@ -714,6 +715,15 @@ public CompletableFuture zrankWithScore(@NonNull String key, @NonNull Zrank, new String[] {key, member, WITH_SCORE_REDIS_API}, this::handleArrayOrNullResponse); } + @Override + public CompletableFuture zmscore(@NonNull String key, @NonNull String[] members) { + String[] arguments = ArrayUtils.addFirst(members, key); + return commandManager.submitNewCommand( + ZMScore, + arguments, + response -> castArray(handleArrayOrNullResponse(response), Double.class)); + } + @Override public CompletableFuture xadd(@NonNull String key, @NonNull Map values) { return xadd(key, values, StreamAddOptions.builder().build()); diff --git a/java/client/src/main/java/glide/api/commands/SortedSetBaseCommands.java b/java/client/src/main/java/glide/api/commands/SortedSetBaseCommands.java index d4a9e5d4ea..0e048a3bfe 100644 --- a/java/client/src/main/java/glide/api/commands/SortedSetBaseCommands.java +++ b/java/client/src/main/java/glide/api/commands/SortedSetBaseCommands.java @@ -456,4 +456,22 @@ CompletableFuture> zrangeWithScores( * } */ CompletableFuture zrankWithScore(String key, String member); + + /** + * Returns the scores associated with the specified members in the sorted set stored + * at key. + * + * @see redis.io for more details. + * @param key The key of the sorted set. + * @param members An array of members in the sorted set. + * @return An Array of scores of the members.
+ * If a member does not exist, the corresponding value in the Array + * will be null. + * @example + *
{@code
+     * Double[] payload = client.zmscore(key1, new String[] {"one", "nonExistentMember", "three"}).get();
+     * assert payload.equals(new Double[] {1.0, null, 3.0});
+     * }
+ */ + CompletableFuture zmscore(String key, String[] members); } 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 9a59ce1b46..a467e5bdf6 100644 --- a/java/client/src/main/java/glide/api/models/BaseTransaction.java +++ b/java/client/src/main/java/glide/api/models/BaseTransaction.java @@ -71,6 +71,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.Type; import static redis_request.RedisRequestOuterClass.RequestType.Unlink; import static redis_request.RedisRequestOuterClass.RequestType.XAdd; +import static redis_request.RedisRequestOuterClass.RequestType.ZMScore; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMax; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMin; import static redis_request.RedisRequestOuterClass.RequestType.ZScore; @@ -1514,6 +1515,23 @@ public T zrankWithScore(@NonNull String key, @NonNull String member) { return getThis(); } + /** + * Returns the scores associated with the specified members in the sorted set stored + * at key. + * + * @see redis.io for more details. + * @param key The key of the sorted set. + * @param members An array of members in the sorted set. + * @return Command Response - An Array of scores of the members.
+ * If a member does not exist, the corresponding value in the Array + * will be null. + */ + public T zmscore(@NonNull String key, @NonNull String[] members) { + ArgsArray commandArgs = buildArgs(ArrayUtils.addFirst(members, key)); + protobufTransaction.addCommands(buildCommand(ZMScore, commandArgs)); + return getThis(); + } + /** * Adds an entry to the specified stream. * diff --git a/java/client/src/test/java/glide/api/RedisClientTest.java b/java/client/src/test/java/glide/api/RedisClientTest.java index 76c03d123e..c16a7c13eb 100644 --- a/java/client/src/test/java/glide/api/RedisClientTest.java +++ b/java/client/src/test/java/glide/api/RedisClientTest.java @@ -91,6 +91,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.Type; import static redis_request.RedisRequestOuterClass.RequestType.Unlink; import static redis_request.RedisRequestOuterClass.RequestType.XAdd; +import static redis_request.RedisRequestOuterClass.RequestType.ZMScore; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMax; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMin; import static redis_request.RedisRequestOuterClass.RequestType.ZScore; @@ -2269,6 +2270,31 @@ public void zrankWithScore_returns_success() { assertEquals(value, payload); } + @SneakyThrows + @Test + public void zmscore_returns_success() { + // setup + String key = "testKey"; + String[] members = new String[] {"member1", "member2"}; + String[] arguments = new String[] {key, "member1", "member2"}; + Double[] value = new Double[] {2.5, 8.2}; + + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(value); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(ZMScore), eq(arguments), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.zmscore(key, members); + Double[] payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(value, payload); + } + @SneakyThrows @Test public void xadd_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 079ee894a9..da8296e34c 100644 --- a/java/client/src/test/java/glide/api/models/TransactionTests.java +++ b/java/client/src/test/java/glide/api/models/TransactionTests.java @@ -76,6 +76,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.Type; import static redis_request.RedisRequestOuterClass.RequestType.Unlink; import static redis_request.RedisRequestOuterClass.RequestType.XAdd; +import static redis_request.RedisRequestOuterClass.RequestType.ZMScore; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMax; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMin; import static redis_request.RedisRequestOuterClass.RequestType.ZScore; @@ -343,6 +344,12 @@ public void transaction_builds_protobuf_request(BaseTransaction transaction) transaction.zrankWithScore("key", "member"); results.add(Pair.of(Zrank, buildArgs("key", "member", WITH_SCORE_REDIS_API))); + transaction.zmscore("key", new String[] {"member1", "member2"}); + results.add( + Pair.of( + ZMScore, + ArgsArray.newBuilder().addArgs("key").addArgs("member1").addArgs("member2").build())); + transaction.xadd("key", Map.of("field1", "foo1")); results.add(Pair.of(XAdd, buildArgs("key", "*", "field1", "foo1"))); diff --git a/java/integTest/src/test/java/glide/SharedCommandTests.java b/java/integTest/src/test/java/glide/SharedCommandTests.java index 3017847a45..fa4866a79c 100644 --- a/java/integTest/src/test/java/glide/SharedCommandTests.java +++ b/java/integTest/src/test/java/glide/SharedCommandTests.java @@ -1315,6 +1315,33 @@ public void zrank(BaseClient client) { assertTrue(executionException.getCause() instanceof RequestException); } + @SneakyThrows + @ParameterizedTest + @MethodSource("getClients") + public void zmscore(BaseClient client) { + String key1 = UUID.randomUUID().toString(); + String key2 = UUID.randomUUID().toString(); + Map membersScores = Map.of("one", 1.0, "two", 2.0, "three", 3.0); + assertEquals(3, client.zadd(key1, membersScores).get()); + assertArrayEquals( + new Double[] {1.0, 2.0, 3.0}, + client.zmscore(key1, new String[] {"one", "two", "three"}).get()); + assertArrayEquals( + new Double[] {1.0, null, null, 3.0}, + client + .zmscore(key1, new String[] {"one", "nonExistentMember", "nonExistentMember", "three"}) + .get()); + assertArrayEquals( + new Double[] {null}, client.zmscore("nonExistentKey", new String[] {"one"}).get()); + + // Key exists, but it is not a set + assertEquals(OK, client.set(key2, "bar").get()); + ExecutionException executionException = + assertThrows( + ExecutionException.class, () -> client.zmscore(key2, new String[] {"one"}).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 95e1014727..d93dd7362f 100644 --- a/java/integTest/src/test/java/glide/TransactionTestUtilities.java +++ b/java/integTest/src/test/java/glide/TransactionTestUtilities.java @@ -101,6 +101,7 @@ public static BaseTransaction transactionTest(BaseTransaction baseTransact baseTransaction.zaddIncr(key8, "one", 3); baseTransaction.zrem(key8, new String[] {"one"}); baseTransaction.zcard(key8); + baseTransaction.zmscore(key8, new String[] {"two", "three"}); baseTransaction.zrange(key8, new RangeByIndex(0, 1)); baseTransaction.zrangeWithScores(key8, new RangeByIndex(0, 1)); baseTransaction.zscore(key8, "two"); @@ -192,6 +193,7 @@ public static Object[] transactionTestResult() { 4.0, 1L, 2L, + new Double[] {2.0, 3.0}, // zmscore(key8, new String[] {"two", "three"}) new String[] {"two", "three"}, // zrange Map.of("two", 2.0, "three", 3.0), // zrangeWithScores 2.0, // zscore(key8, "two")