Skip to content

Commit

Permalink
Java: Added Zrem and Zcard commands. (Sorted Set Commands) (valkey-io…
Browse files Browse the repository at this point in the history
…#1119)

* Java: Added Zrem and Zcard commands. (Sorted Set Commands)

* Added exception cases to IT tests.
  • Loading branch information
SanHalacogluImproving authored Mar 18, 2024
1 parent 54c498e commit 232f077
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 0 deletions.
13 changes: 13 additions & 0 deletions java/client/src/main/java/glide/api/BaseClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import static redis_request.RedisRequestOuterClass.RequestType.TTL;
import static redis_request.RedisRequestOuterClass.RequestType.Unlink;
import static redis_request.RedisRequestOuterClass.RequestType.Zadd;
import static redis_request.RedisRequestOuterClass.RequestType.Zcard;
import static redis_request.RedisRequestOuterClass.RequestType.Zrem;

import glide.api.commands.GenericBaseCommands;
import glide.api.commands.HashBaseCommands;
Expand Down Expand Up @@ -573,4 +575,15 @@ public CompletableFuture<Double> zaddIncr(

return commandManager.submitNewCommand(Zadd, arguments, this::handleDoubleResponse);
}

@Override
public CompletableFuture<Long> zrem(@NonNull String key, @NonNull String[] members) {
String[] arguments = ArrayUtils.addFirst(members, key);
return commandManager.submitNewCommand(Zrem, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> zcard(@NonNull String key) {
return commandManager.submitNewCommand(Zcard, new String[] {key}, this::handleLongResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,45 @@ CompletableFuture<Double> zaddIncr(
* }</pre>
*/
CompletableFuture<Double> zaddIncr(String key, String member, double increment);

/**
* Removes the specified members from the sorted set stored at <code>key</code>.<br>
* Specified members that are not a member of this set are ignored.
*
* @see <a href="https://redis.io/commands/zrem/">redis.io</a> for more details.
* @param key The key of the sorted set.
* @param members An array of members to remove from the sorted set.
* @return The number of members that were removed from the sorted set, not including non-existing
* members.<br>
* If <code>key</code> does not exist, it is treated as an empty sorted set, and this command
* returns <code>0</code>.
* @example
* <pre>{@code
* Long num1 = client.zrem("mySortedSet", new String[] {"member1", "member2"}).get();
* assert num1 == 2L; // Indicates that two members have been removed from the sorted set "mySortedSet".
*
* Long num2 = client.zrem("nonExistingSortedSet", new String[] {"member1", "member2"}).get();
* assert num2 == 0L; // Indicates that no members were removed as the sorted set "nonExistingSortedSet" does not exist.
* }</pre>
*/
CompletableFuture<Long> zrem(String key, String[] members);

/**
* Returns the cardinality (number of elements) of the sorted set stored at <code>key</code>.
*
* @see <a href="https://redis.io/commands/zcard/">redis.io</a> for more details.
* @param key The key of the sorted set.
* @return The number of elements in the sorted set.<br>
* If <code>key</code> does not exist, it is treated as an empty sorted set, and this command
* return <code>0</code>.
* @example
* <pre>{@code
* Long num1 = client.zcard("mySortedSet").get();
* assert num1 == 3L; // Indicates that there are 3 elements in the sorted set "mySortedSet".
*
* Long num2 = client.zcard("nonExistingSortedSet").get();
* assert num2 == 0L;
* }</pre>
*/
CompletableFuture<Long> zcard(String key);
}
35 changes: 35 additions & 0 deletions java/client/src/main/java/glide/api/models/BaseTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
import static redis_request.RedisRequestOuterClass.RequestType.TTL;
import static redis_request.RedisRequestOuterClass.RequestType.Unlink;
import static redis_request.RedisRequestOuterClass.RequestType.Zadd;
import static redis_request.RedisRequestOuterClass.RequestType.Zcard;
import static redis_request.RedisRequestOuterClass.RequestType.Zrem;

import glide.api.models.commands.ExpireOptions;
import glide.api.models.commands.InfoOptions;
Expand Down Expand Up @@ -1172,6 +1174,39 @@ public T zaddIncr(@NonNull String key, @NonNull String member, double increment)
return getThis().zaddIncr(key, member, increment, ZaddOptions.builder().build());
}

/**
* Removes the specified members from the sorted set stored at <code>key</code>.<br>
* Specified members that are not a member of this set are ignored.
*
* @see <a href="https://redis.io/commands/zrem/">redis.io</a> for more details.
* @param key The key of the sorted set.
* @param members An array of members to remove from the sorted set.
* @return Command Response - The number of members that were removed from the sorted set, not
* including non-existing members.<br>
* If <code>key</code> does not exist, it is treated as an empty sorted set, and this command
* returns <code>0</code>.
*/
public T zrem(@NonNull String key, @NonNull String[] members) {
ArgsArray commandArgs = buildArgs(ArrayUtils.addFirst(members, key));
protobufTransaction.addCommands(buildCommand(Zrem, commandArgs));
return getThis();
}

/**
* Returns the cardinality (number of elements) of the sorted set stored at <code>key</code>.
*
* @see <a href="https://redis.io/commands/zcard/">redis.io</a> for more details.
* @param key The key of the sorted set.
* @return Command Response - The number of elements in the sorted set.<br>
* If <code>key</code> does not exist, it is treated as an empty sorted set, and this command
* return <code>0</code>.
*/
public T zcard(@NonNull String key) {
ArgsArray commandArgs = buildArgs(new String[] {key});
protobufTransaction.addCommands(buildCommand(Zcard, commandArgs));
return getThis();
}

/** Build protobuf {@link Command} object for given command and arguments. */
protected Command buildCommand(RequestType requestType) {
return buildCommand(requestType, buildArgs());
Expand Down
51 changes: 51 additions & 0 deletions java/client/src/test/java/glide/api/RedisClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
import static redis_request.RedisRequestOuterClass.RequestType.TTL;
import static redis_request.RedisRequestOuterClass.RequestType.Unlink;
import static redis_request.RedisRequestOuterClass.RequestType.Zadd;
import static redis_request.RedisRequestOuterClass.RequestType.Zcard;
import static redis_request.RedisRequestOuterClass.RequestType.Zrem;

import glide.api.models.commands.ExpireOptions;
import glide.api.models.commands.InfoOptions;
Expand Down Expand Up @@ -1541,4 +1543,53 @@ public void configResetStat_returns_success() {
assertEquals(testResponse, response);
assertEquals(OK, payload);
}

@SneakyThrows
@Test
public void zrem_returns_success() {
// setup
String key = "testKey";
String[] members = new String[] {"member1", "member2"};
String[] arguments = ArrayUtils.addFirst(members, key);
Long value = 2L;

CompletableFuture<Long> testResponse = mock(CompletableFuture.class);
when(testResponse.get()).thenReturn(value);

// match on protobuf request
when(commandManager.<Long>submitNewCommand(eq(Zrem), eq(arguments), any()))
.thenReturn(testResponse);

// exercise
CompletableFuture<Long> response = service.zrem(key, members);
Long payload = response.get();

// verify
assertEquals(testResponse, response);
assertEquals(value, payload);
}

@SneakyThrows
@Test
public void zcard_returns_success() {
// setup
String key = "testKey";
String[] arguments = new String[] {key};
Long value = 3L;

CompletableFuture<Long> testResponse = mock(CompletableFuture.class);
when(testResponse.get()).thenReturn(value);

// match on protobuf request
when(commandManager.<Long>submitNewCommand(eq(Zcard), eq(arguments), any()))
.thenReturn(testResponse);

// exercise
CompletableFuture<Long> response = service.zcard(key);
Long payload = response.get();

// verify
assertEquals(testResponse, response);
assertEquals(value, payload);
}
}
11 changes: 11 additions & 0 deletions java/client/src/test/java/glide/api/models/TransactionTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
import static redis_request.RedisRequestOuterClass.RequestType.TTL;
import static redis_request.RedisRequestOuterClass.RequestType.Unlink;
import static redis_request.RedisRequestOuterClass.RequestType.Zadd;
import static redis_request.RedisRequestOuterClass.RequestType.Zcard;
import static redis_request.RedisRequestOuterClass.RequestType.Zrem;

import glide.api.models.commands.ExpireOptions;
import glide.api.models.commands.InfoOptions;
Expand Down Expand Up @@ -335,6 +337,15 @@ public void transaction_builds_protobuf_request(BaseTransaction<?> transaction)
.addArgs("member1")
.build()));

transaction.zrem("key", new String[] {"member1", "member2"});
results.add(
Pair.of(
Zrem,
ArgsArray.newBuilder().addArgs("key").addArgs("member1").addArgs("member2").build()));

transaction.zcard("key");
results.add(Pair.of(Zcard, ArgsArray.newBuilder().addArgs("key").build()));

var protobufTransaction = transaction.getProtobufTransaction().build();

for (int idx = 0; idx < protobufTransaction.getCommandsCount(); idx++) {
Expand Down
39 changes: 39 additions & 0 deletions java/integTest/src/test/java/glide/SharedCommandTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -972,4 +972,43 @@ public void zadd_illegal_arguments(BaseClient client) {
.build();
options.toArgs();
}

@SneakyThrows
@ParameterizedTest
@MethodSource("getClients")
public void zrem(BaseClient client) {
String key = UUID.randomUUID().toString();
Map<String, Double> membersScores = Map.of("one", 1.0, "two", 2.0, "three", 3.0);
assertEquals(3, client.zadd(key, membersScores).get());
assertEquals(1, client.zrem(key, new String[] {"one"}).get());
assertEquals(2, client.zrem(key, new String[] {"one", "two", "three"}).get());
assertEquals(0, client.zrem("non_existing_set", new String[] {"member"}).get());

// Key exists, but it is not a set
assertEquals(OK, client.set("foo", "bar").get());
ExecutionException executionException =
assertThrows(
ExecutionException.class, () -> client.zrem("foo", new String[] {"bar"}).get());
assertTrue(executionException.getCause() instanceof RequestException);
}

@SneakyThrows
@ParameterizedTest
@MethodSource("getClients")
public void zcard(BaseClient client) {
String key = UUID.randomUUID().toString();
Map<String, Double> membersScores = Map.of("one", 1.0, "two", 2.0, "three", 3.0);
assertEquals(3, client.zadd(key, membersScores).get());
assertEquals(3, client.zcard(key).get());
assertEquals(1, client.zrem(key, new String[] {"one"}).get());
assertEquals(2, client.zcard(key).get());

assertEquals(0, client.zcard("nonExistentSet").get());

// Key exists, but it is not a set
assertEquals(OK, client.set("foo", "bar").get());
ExecutionException executionException =
assertThrows(ExecutionException.class, () -> client.zcard("foo").get());
assertTrue(executionException.getCause() instanceof RequestException);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ public static BaseTransaction<?> transactionTest(BaseTransaction<?> baseTransact

baseTransaction.zadd(key8, Map.of("one", 1.0, "two", 2.0, "three", 3.0));
baseTransaction.zaddIncr(key8, "one", 3);
baseTransaction.zrem(key8, new String[] {"one"});
baseTransaction.zcard(key8);

baseTransaction.configResetStat();

Expand Down Expand Up @@ -132,6 +134,8 @@ public static Object[] transactionTestResult() {
Set.of("baz"),
3L,
4.0,
1L,
2L,
OK
};
}
Expand Down

0 comments on commit 232f077

Please sign in to comment.