Skip to content

Commit

Permalink
Java: Add Lrem command to BaseClient and BaseTransaction. (List comma…
Browse files Browse the repository at this point in the history
…nds) (valkey-io#1073)

* Java: Add Lrem command to BaseClient and BaseTransaction. (List commands)

* Minor update IT tests.
  • Loading branch information
SanHalacogluImproving authored Mar 7, 2024
1 parent 12343d8 commit b1ef52b
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 3 deletions.
7 changes: 7 additions & 0 deletions java/client/src/main/java/glide/api/BaseClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.LPop;
import static redis_request.RedisRequestOuterClass.RequestType.LPush;
import static redis_request.RedisRequestOuterClass.RequestType.LRange;
import static redis_request.RedisRequestOuterClass.RequestType.LRem;
import static redis_request.RedisRequestOuterClass.RequestType.LTrim;
import static redis_request.RedisRequestOuterClass.RequestType.MGet;
import static redis_request.RedisRequestOuterClass.RequestType.MSet;
Expand Down Expand Up @@ -384,6 +385,12 @@ public CompletableFuture<Long> llen(@NonNull String key) {
return commandManager.submitNewCommand(LLen, new String[] {key}, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> lrem(@NonNull String key, long count, @NonNull String element) {
return commandManager.submitNewCommand(
LRem, new String[] {key, Long.toString(count), element}, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> rpush(@NonNull String key, @NonNull String[] elements) {
String[] arguments = ArrayUtils.addFirst(elements, key);
Expand Down
24 changes: 24 additions & 0 deletions java/client/src/main/java/glide/api/commands/ListBaseCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,30 @@ public interface ListBaseCommands {
*/
CompletableFuture<Long> llen(String key);

/**
* Removes the first <code>count</code> occurrences of elements equal to <code>element</code> from
* the list stored at <code>key</code>.<br>
* If <code>count</code> is positive: Removes elements equal to <code>element</code> moving from
* head to tail.<br>
* If <code>count</code> is negative: Removes elements equal to <code>element</code> moving from
* tail to head.<br>
* If <code>count</code> is 0 or <code>count</code> is greater than the occurrences of elements
* equal to <code>element</code>, it removes all elements equal to <code>element</code>.<br>
*
* @see <a href="https://redis.io/commands/lrem/">redis.io</a> for details.
* @param key The key of the list.
* @param count The count of the occurrences of elements equal to <code>element</code> to remove.
* @param element The element to remove from the list.
* @return The number of the removed elements.<br>
* If <code>key</code> does not exist, 0 is returned.<br>
* @example
* <pre>{@code
* Long num = client.rem("my_list", 2, "value").get();
* assert num == 2L;
* }</pre>
*/
CompletableFuture<Long> lrem(String key, long count, String element);

/**
* Inserts all the specified values at the tail of the list stored at <code>key</code>.<br>
* <code>elements</code> are inserted one after the other to the tail of the list, from the
Expand Down
25 changes: 25 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 @@ -30,6 +30,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.LPop;
import static redis_request.RedisRequestOuterClass.RequestType.LPush;
import static redis_request.RedisRequestOuterClass.RequestType.LRange;
import static redis_request.RedisRequestOuterClass.RequestType.LRem;
import static redis_request.RedisRequestOuterClass.RequestType.LTrim;
import static redis_request.RedisRequestOuterClass.RequestType.MGet;
import static redis_request.RedisRequestOuterClass.RequestType.MSet;
Expand Down Expand Up @@ -600,6 +601,30 @@ public T llen(@NonNull String key) {
return getThis();
}

/**
* Removes the first <code>count</code> occurrences of elements equal to <code>element</code> from
* the list stored at <code>key</code>.<br>
* If <code>count</code> is positive: Removes elements equal to <code>element</code> moving from
* head to tail.<br>
* If <code>count</code> is negative: Removes elements equal to <code>element</code> moving from
* tail to head.<br>
* If <code>count</code> is 0 or <code>count</code> is greater than the occurrences of elements
* equal to <code>element</code>, it removes all elements equal to <code>element</code>.<br>
*
* @see <a href="https://redis.io/commands/lrem/">redis.io</a> for details.
* @param key The key of the list.
* @param count The count of the occurrences of elements equal to <code>element</code> to remove.
* @param element The element to remove from the list.
* @return Command Response - The number of the removed elements.<br>
* If <code>key</code> does not exist, 0 is returned.<br>
*/
public T lrem(@NonNull String key, long count, @NonNull String element) {
ArgsArray commandArgs = buildArgs(key, Long.toString(count), element);

protobufTransaction.addCommands(buildCommand(LRem, commandArgs));
return getThis();
}

/**
* Inserts all the specified values at the tail of the list stored at <code>key</code>.<br>
* <code>elements</code> are inserted one after the other to the tail of the list, from the
Expand Down
26 changes: 26 additions & 0 deletions java/client/src/test/java/glide/api/RedisClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.LPop;
import static redis_request.RedisRequestOuterClass.RequestType.LPush;
import static redis_request.RedisRequestOuterClass.RequestType.LRange;
import static redis_request.RedisRequestOuterClass.RequestType.LRem;
import static redis_request.RedisRequestOuterClass.RequestType.LTrim;
import static redis_request.RedisRequestOuterClass.RequestType.MGet;
import static redis_request.RedisRequestOuterClass.RequestType.MSet;
Expand Down Expand Up @@ -1121,6 +1122,31 @@ public void llen_returns_success() {
assertEquals(value, payload);
}

@SneakyThrows
@Test
public void lrem_returns_success() {
// setup
String key = "testKey";
long count = 2L;
String element = "value";
String[] args = new String[] {key, Long.toString(count), element};
long value = 2L;

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

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

// exercise
CompletableFuture<Long> response = service.lrem(key, count, element);
Long payload = response.get();

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

@SneakyThrows
@Test
public void rpush_returns_success() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.LPop;
import static redis_request.RedisRequestOuterClass.RequestType.LPush;
import static redis_request.RedisRequestOuterClass.RequestType.LRange;
import static redis_request.RedisRequestOuterClass.RequestType.LRem;
import static redis_request.RedisRequestOuterClass.RequestType.LTrim;
import static redis_request.RedisRequestOuterClass.RequestType.MGet;
import static redis_request.RedisRequestOuterClass.RequestType.MSet;
Expand Down Expand Up @@ -183,6 +184,11 @@ public void transaction_builds_protobuf_request(BaseTransaction<?> transaction)
transaction.llen("key");
results.add(Pair.of(LLen, ArgsArray.newBuilder().addArgs("key").build()));

transaction.lrem("key", 1, "element");
results.add(
Pair.of(
LRem, ArgsArray.newBuilder().addArgs("key").addArgs("1").addArgs("element").build()));

transaction.rpush("key", new String[] {"element"});
results.add(Pair.of(RPush, ArgsArray.newBuilder().addArgs("key").addArgs("element").build()));

Expand Down
24 changes: 24 additions & 0 deletions java/integTest/src/test/java/glide/SharedCommandTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,30 @@ public void llen_existing_non_existing_key_and_type_error(BaseClient client) {
assertTrue(lrangeException.getCause() instanceof RequestException);
}

@SneakyThrows
@ParameterizedTest
@MethodSource("getClients")
public void lrem_existing_non_existing_key_and_type_error(BaseClient client) {
String key = UUID.randomUUID().toString();
String[] valueArray =
new String[] {
"value1", "value2", "value1", "value1", "value2",
};

assertEquals(5, client.lpush(key, valueArray).get());
assertEquals(2, client.lrem(key, 2, "value1").get());
assertArrayEquals(
new String[] {
"value2", "value2", "value1",
},
client.lrange(key, 0, -1).get());
assertEquals(1, client.lrem(key, -1, "value2").get());
assertArrayEquals(new String[] {"value2", "value1"}, client.lrange(key, 0, -1).get());
assertEquals(1, client.lrem(key, 0, "value2").get());
assertArrayEquals(new String[] {"value1"}, client.lrange(key, 0, -1).get());
assertEquals(0, client.lrem("non_existing_key", 0, "value").get());
}

@SneakyThrows
@ParameterizedTest
@MethodSource("getClients")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ public static BaseTransaction<?> transactionTest(BaseTransaction<?> baseTransact
baseTransaction.hincrBy(key4, field3, 5);
baseTransaction.hincrByFloat(key4, field3, 5.5);

baseTransaction.lpush(key5, new String[] {value1, value2, value3, value3});
baseTransaction.lpush(key5, new String[] {value1, value1, value2, value3, value3});
baseTransaction.llen(key5);
baseTransaction.lrem(key5, 1, value1);
baseTransaction.ltrim(key5, 1, -1);
baseTransaction.lrange(key5, 0, -2);
baseTransaction.lpop(key5);
Expand Down Expand Up @@ -111,8 +112,9 @@ public static Object[] transactionTestResult() {
1L,
5L,
10.5,
4L,
4L,
5L,
5L,
1L,
OK,
new String[] {value3, value2},
value3,
Expand Down

0 comments on commit b1ef52b

Please sign in to comment.