Skip to content

Commit

Permalink
support zintercard, zdiffstore, zremrangebyrank, lpush, lpushx, lrem,… (
Browse files Browse the repository at this point in the history
valkey-io#1634)

support zintercard, zdiffstore, zremrangebyrank, lpush, lpushx, lrem, rpus and rpushx with GlideString
  • Loading branch information
alon-arenberg authored Jun 24, 2024
1 parent d6595bf commit 66d97e5
Show file tree
Hide file tree
Showing 4 changed files with 485 additions and 0 deletions.
69 changes: 69 additions & 0 deletions java/client/src/main/java/glide/api/BaseClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,12 @@ public CompletableFuture<Long> lpush(@NonNull String key, @NonNull String[] elem
return commandManager.submitNewCommand(LPush, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> lpush(@NonNull GlideString key, @NonNull GlideString[] elements) {
GlideString[] arguments = ArrayUtils.addFirst(elements, key);
return commandManager.submitNewCommand(LPush, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<String> lpop(@NonNull String key) {
return commandManager.submitNewCommand(
Expand Down Expand Up @@ -948,12 +954,27 @@ public CompletableFuture<Long> lrem(@NonNull String key, long count, @NonNull St
LRem, new String[] {key, Long.toString(count), element}, this::handleLongResponse);
}

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

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

@Override
public CompletableFuture<Long> rpush(@NonNull GlideString key, @NonNull GlideString[] elements) {
GlideString[] arguments = ArrayUtils.addFirst(elements, key);
return commandManager.submitNewCommand(RPush, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<String> rpop(@NonNull String key) {
return commandManager.submitNewCommand(
Expand Down Expand Up @@ -1332,6 +1353,15 @@ public CompletableFuture<Long> zdiffstore(@NonNull String destination, @NonNull
return commandManager.submitNewCommand(ZDiffStore, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> zdiffstore(
@NonNull GlideString destination, @NonNull GlideString[] keys) {
GlideString[] arguments =
ArrayUtils.addAll(
new GlideString[] {destination, gs(Long.toString(keys.length).getBytes())}, keys);
return commandManager.submitNewCommand(ZDiffStore, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> zcount(
@NonNull String key, @NonNull ScoreRange minScore, @NonNull ScoreRange maxScore) {
Expand All @@ -1347,6 +1377,16 @@ public CompletableFuture<Long> zremrangebyrank(@NonNull String key, long start,
this::handleLongResponse);
}

@Override
public CompletableFuture<Long> zremrangebyrank(@NonNull GlideString key, long start, long end) {
return commandManager.submitNewCommand(
ZRemRangeByRank,
new GlideString[] {
key, gs(Long.toString(start).getBytes()), gs(Long.toString(end).getBytes())
},
this::handleLongResponse);
}

@Override
public CompletableFuture<Long> zremrangebylex(
@NonNull String key, @NonNull LexRange minLex, @NonNull LexRange maxLex) {
Expand Down Expand Up @@ -1517,6 +1557,13 @@ public CompletableFuture<Long> zintercard(@NonNull String[] keys) {
return commandManager.submitNewCommand(ZInterCard, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> zintercard(@NonNull GlideString[] keys) {
GlideString[] arguments =
ArrayUtils.addFirst(keys, gs(Integer.toString(keys.length).getBytes()));
return commandManager.submitNewCommand(ZInterCard, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> zintercard(@NonNull String[] keys, long limit) {
String[] arguments =
Expand All @@ -1527,6 +1574,16 @@ public CompletableFuture<Long> zintercard(@NonNull String[] keys, long limit) {
return commandManager.submitNewCommand(ZInterCard, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> zintercard(@NonNull GlideString[] keys, long limit) {
GlideString[] arguments =
concatenateArrays(
new GlideString[] {gs(Integer.toString(keys.length).getBytes())},
keys,
new GlideString[] {gs(LIMIT_REDIS_API), gs(Long.toString(limit).getBytes())});
return commandManager.submitNewCommand(ZInterCard, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<String> xadd(@NonNull String key, @NonNull Map<String, String> values) {
return xadd(key, values, StreamAddOptions.builder().build());
Expand Down Expand Up @@ -1724,12 +1781,24 @@ public CompletableFuture<Long> rpushx(@NonNull String key, @NonNull String[] ele
return commandManager.submitNewCommand(RPushX, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> rpushx(@NonNull GlideString key, @NonNull GlideString[] elements) {
GlideString[] arguments = ArrayUtils.addFirst(elements, key);
return commandManager.submitNewCommand(RPushX, arguments, this::handleLongResponse);
}

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

@Override
public CompletableFuture<Long> lpushx(@NonNull GlideString key, @NonNull GlideString[] elements) {
GlideString[] arguments = ArrayUtils.addFirst(elements, key);
return commandManager.submitNewCommand(LPushX, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<String[]> zrange(
@NonNull String key, @NonNull RangeQuery rangeQuery, boolean reverse) {
Expand Down
100 changes: 100 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 @@ -40,6 +40,27 @@ public interface ListBaseCommands {
*/
CompletableFuture<Long> lpush(String key, String[] elements);

/**
* Inserts all the specified values at the head of the list stored at <code>key</code>. <code>
* elements</code> are inserted one after the other to the head of the list, from the leftmost
* element to the rightmost element. If <code>key</code> does not exist, it is created as an empty
* list before performing the push operation.
*
* @see <a href="https://redis.io/commands/lpush/">redis.io</a> for details.
* @param key The key of the list.
* @param elements The elements to insert at the head of the list stored at <code>key</code>.
* @return The length of the list after the push operation.
* @example
* <pre>{@code
* Long pushCount1 = client.lpush(gs("my_list"), new GlideString[] {gs("value1"), gs("value2")}).get();
* assert pushCount1 == 2L;
*
* Long pushCount2 = client.lpush(gs("nonexistent_list"), new GlideString[] {gs("new_value")}).get();
* assert pushCount2 == 1L;
* }</pre>
*/
CompletableFuture<Long> lpush(GlideString key, GlideString[] elements);

/**
* Removes and returns the first elements of the list stored at <code>key</code>. The command pops
* a single element from the beginning of the list.
Expand Down Expand Up @@ -312,6 +333,30 @@ CompletableFuture<Long[]> lposCount(
*/
CompletableFuture<Long> lrem(String key, long count, String element);

/**
* 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>.
*
* @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, <code>0</code> is returned.
* @example
* <pre>{@code
* Long num = client.rem(gs("my_list"), 2, gs("value")).get();
* assert num == 2L;
* }</pre>
*/
CompletableFuture<Long> lrem(GlideString key, long count, GlideString 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 All @@ -333,6 +378,27 @@ CompletableFuture<Long[]> lposCount(
*/
CompletableFuture<Long> rpush(String key, String[] elements);

/**
* 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
* leftmost element to the rightmost element. If <code>key</code> does not exist, it is created as
* an empty list before performing the push operation.
*
* @see <a href="https://redis.io/commands/rpush/">redis.io</a> for details.
* @param key The key of the list.
* @param elements The elements to insert at the tail of the list stored at <code>key</code>.
* @return The length of the list after the push operation.
* @example
* <pre>{@code
* Long pushCount1 = client.rpush(gs("my_list"), new GlideString[] {gs("value1"), gs("value2")}).get();
* assert pushCount1 == 2L;
*
* Long pushCount2 = client.rpush(gs("nonexistent_list"), new GlideString[] {gs("new_value")}).get();
* assert pushCount2 == 1L;
* }</pre>
*/
CompletableFuture<Long> rpush(GlideString key, GlideString[] elements);

/**
* Removes and returns the last elements of the list stored at <code>key</code>.<br>
* The command pops a single element from the end of the list.
Expand Down Expand Up @@ -471,6 +537,23 @@ CompletableFuture<Long> linsert(
*/
CompletableFuture<Long> rpushx(String key, String[] elements);

/**
* Inserts all the specified values at the tail of the list stored at <code>key</code>, only if
* <code>key</code> exists and holds a list. If <code>key</code> is not a list, this performs no
* operation.
*
* @see <a href="https://redis.io/commands/rpushx/">redis.io</a> for details.
* @param key The key of the list.
* @param elements The elements to insert at the tail of the list stored at <code>key</code>.
* @return The length of the list after the push operation.
* @example
* <pre>{@code
* Long listLength = client.rpushx(gs("my_list"), new GlideString[] {gs("value1"), gs("value2")}).get();
* assert listLength >= 2L;
* }</pre>
*/
CompletableFuture<Long> rpushx(GlideString key, GlideString[] elements);

/**
* Inserts all the specified values at the head of the list stored at <code>key</code>, only if
* <code>key</code> exists and holds a list. If <code>key</code> is not a list, this performs no
Expand All @@ -488,6 +571,23 @@ CompletableFuture<Long> linsert(
*/
CompletableFuture<Long> lpushx(String key, String[] elements);

/**
* Inserts all the specified values at the head of the list stored at <code>key</code>, only if
* <code>key</code> exists and holds a list. If <code>key</code> is not a list, this performs no
* operation.
*
* @see <a href="https://redis.io/commands/lpushx/">redis.io</a> for details.
* @param key The key of the list.
* @param elements The elements to insert at the head of the list stored at <code>key</code>.
* @return The length of the list after the push operation.
* @example
* <pre>{@code
* Long listLength = client.lpushx(gs("my_list"), new GlideString[] {gs("value1"), gs("value2")}).get();
* assert listLength >= 2L;
* }</pre>
*/
CompletableFuture<Long> lpushx(GlideString key, GlideString[] elements);

/**
* Pops one or more elements from the first non-empty list from the provided <code>keys
* </code>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,26 @@ CompletableFuture<Long> zrangestore(
*/
CompletableFuture<Long> zdiffstore(String destination, String[] keys);

/**
* Calculates the difference between the first sorted set and all the successive sorted sets at
* <code>keys</code> and stores the difference as a sorted set to <code>destination</code>,
* overwriting it if it already exists. Non-existent keys are treated as empty sets.
*
* @apiNote When in cluster mode, <code>destination</code> and all <code>keys</code> must map to
* the same hash slot.
* @since Redis 6.2 and above.
* @see <a href="https://redis.io/commands/zdiffstore/">redis.io</a> for more details.
* @param destination The key for the resulting sorted set.
* @param keys The keys of the sorted sets to compare.
* @return The number of members in the resulting sorted set stored at <code>destination</code>.
* @example
* <pre>{@code
* Long payload = client.zdiffstore(gs("mySortedSet"), new GlideString[] {gs("key1"), gs("key2")}).get();
* assert payload > 0; // At least one member differed in "key1" compared to "key2", and this difference was stored in "mySortedSet".
* }</pre>
*/
CompletableFuture<Long> zdiffstore(GlideString destination, GlideString[] keys);

/**
* Returns the number of members in the sorted set stored at <code>key</code> with scores between
* <code>minScore</code> and <code>maxScore</code>.
Expand Down Expand Up @@ -864,6 +884,33 @@ CompletableFuture<Long> zrangestore(
*/
CompletableFuture<Long> zremrangebyrank(String key, long start, long end);

/**
* Removes all elements in the sorted set stored at <code>key</code> with rank between <code>start
* </code> and <code>end</code>. Both <code>start</code> and <code>end</code> are zero-based
* indexes with <code>0</code> being the element with the lowest score. These indexes can be
* negative numbers, where they indicate offsets starting at the element with the highest score.
*
* @see <a href="https://redis.io/commands/zremrangebyrank/">redis.io</a> for more details.
* @param key The key of the sorted set.
* @param start The starting point of the range.
* @param end The end of the range.
* @return The number of elements removed.<br>
* If <code>start</code> exceeds the end of the sorted set, or if <code>start</code> is
* greater than <code>end</code>, <code>0</code> returned.<br>
* If <code>end</code> exceeds the actual end of the sorted set, the range will stop at the
* actual end of the sorted set.<br>
* If <code>key</code> does not exist <code>0</code> will be returned.
* @example
* <pre>{@code
* Long payload1 = client.zremrangebyrank(gs("mySortedSet"), 0, 4).get();
* assert payload1 == 5L; // Indicates that 5 elements, with ranks ranging from 0 to 4 (inclusive), have been removed from "mySortedSet".
*
* Long payload2 = client.zremrangebyrank(gs("mySortedSet"), 0, 4).get();
* assert payload2 == 0L; // Indicates that nothing was removed.
* }</pre>
*/
CompletableFuture<Long> zremrangebyrank(GlideString key, long start, long end);

/**
* Removes all elements in the sorted set stored at <code>key</code> with a lexicographical order
* between <code>minLex</code> and <code>maxLex</code>.
Expand Down Expand Up @@ -1455,6 +1502,22 @@ CompletableFuture<Map<String, Double>> zinterWithScores(
*/
CompletableFuture<Long> zintercard(String[] keys);

/**
* Returns the cardinality of the intersection of the sorted sets specified by <code>keys</code>.
*
* @apiNote When in cluster mode, all <code>keys</code> must map to the same hash slot.
* @since Redis 7.0 and above.
* @see <a href="https://redis.io/commands/zintercard/">redis.io</a> for more details.
* @param keys The keys of the sorted sets to intersect.
* @return The cardinality of the intersection of the given sorted sets.
* @example
* <pre>{@code
* Long length = client.zintercard(new GlideString[] {gs("mySortedSet1"), gs("mySortedSet2")}).get();
* assert length == 3L;
* }</pre>
*/
CompletableFuture<Long> zintercard(GlideString[] keys);

/**
* Returns the cardinality of the intersection of the sorted sets specified by <code>keys</code>.
* If the intersection cardinality reaches <code>limit</code> partway through the computation, the
Expand All @@ -1475,4 +1538,25 @@ CompletableFuture<Map<String, Double>> zinterWithScores(
* }</pre>
*/
CompletableFuture<Long> zintercard(String[] keys, long limit);

/**
* Returns the cardinality of the intersection of the sorted sets specified by <code>keys</code>.
* If the intersection cardinality reaches <code>limit</code> partway through the computation, the
* algorithm will exit early and yield <code>limit</code> as the cardinality.
*
* @apiNote When in cluster mode, all <code>keys</code> must map to the same hash slot.
* @since Redis 7.0 and above.
* @see <a href="https://redis.io/commands/zintercard/">redis.io</a> for more details.
* @param keys The keys of the sorted sets to intersect.
* @param limit Specifies a maximum number for the intersection cardinality. If limit is set to
* <code>0</code> the range will be unlimited.
* @return The cardinality of the intersection of the given sorted sets, or the <code>limit</code>
* if reached.
* @example
* <pre>{@code
* Long length = client.zintercard(new GlideString[] {gs("mySortedSet1"), gs("mySortedSet2")}, 5).get();
* assert length == 3L;
* }</pre>
*/
CompletableFuture<Long> zintercard(GlideString[] keys, long limit);
}
Loading

0 comments on commit 66d97e5

Please sign in to comment.