Skip to content

Commit

Permalink
binary version of ping, touch, sunion and sunionstore (#1663)
Browse files Browse the repository at this point in the history
* binary version of ping, touch, sunion and sunionstore
  • Loading branch information
talxsha authored Jul 2, 2024
1 parent cdf47fb commit e2aafd7
Show file tree
Hide file tree
Showing 12 changed files with 404 additions and 0 deletions.
17 changes: 17 additions & 0 deletions java/client/src/main/java/glide/api/BaseClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -1486,6 +1486,13 @@ public CompletableFuture<Long> sunionstore(@NonNull String destination, @NonNull
return commandManager.submitNewCommand(SUnionStore, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> sunionstore(
@NonNull GlideString destination, @NonNull GlideString[] keys) {
GlideString[] arguments = ArrayUtils.addFirst(keys, destination);
return commandManager.submitNewCommand(SUnionStore, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> exists(@NonNull String[] keys) {
return commandManager.submitNewCommand(Exists, keys, this::handleLongResponse);
Expand Down Expand Up @@ -2682,6 +2689,11 @@ public CompletableFuture<Long> touch(@NonNull String[] keys) {
return commandManager.submitNewCommand(Touch, keys, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> touch(@NonNull GlideString[] keys) {
return commandManager.submitNewCommand(Touch, keys, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> geoadd(
@NonNull String key,
Expand Down Expand Up @@ -3310,6 +3322,11 @@ public CompletableFuture<Set<String>> sunion(@NonNull String[] keys) {
return commandManager.submitNewCommand(SUnion, keys, this::handleSetResponse);
}

@Override
public CompletableFuture<Set<GlideString>> sunion(@NonNull GlideString[] keys) {
return commandManager.submitNewCommand(SUnion, keys, this::handleSetBinaryResponse);
}

// Hack: convert all `byte[]` -> `GlideString`. Better doing it here in the Java realm
// rather than doing it in the Rust code using JNI calls (performance)
private Object convertByteArrayToGlideString(Object o) {
Expand Down
6 changes: 6 additions & 0 deletions java/client/src/main/java/glide/api/RedisClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ public CompletableFuture<String> ping(@NonNull String message) {
Ping, new String[] {message}, this::handleStringResponse);
}

@Override
public CompletableFuture<GlideString> ping(@NonNull GlideString message) {
return commandManager.submitNewCommand(
Ping, new GlideString[] {message}, this::handleStringResponseBinary);
}

@Override
public CompletableFuture<String> info() {
return commandManager.submitNewCommand(Info, new String[0], this::handleStringResponse);
Expand Down
12 changes: 12 additions & 0 deletions java/client/src/main/java/glide/api/RedisClusterClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@ public CompletableFuture<String> ping(@NonNull String message) {
Ping, new String[] {message}, this::handleStringResponse);
}

@Override
public CompletableFuture<GlideString> ping(@NonNull GlideString message) {
return commandManager.submitNewCommand(
Ping, new GlideString[] {message}, this::handleStringResponseBinary);
}

@Override
public CompletableFuture<String> ping(@NonNull Route route) {
return commandManager.submitNewCommand(Ping, new String[0], route, this::handleStringResponse);
Expand All @@ -165,6 +171,12 @@ public CompletableFuture<String> ping(@NonNull String message, @NonNull Route ro
Ping, new String[] {message}, route, this::handleStringResponse);
}

@Override
public CompletableFuture<GlideString> ping(@NonNull GlideString message, @NonNull Route route) {
return commandManager.submitNewCommand(
Ping, new GlideString[] {message}, route, this::handleStringResponseBinary);
}

@Override
public CompletableFuture<ClusterValue<String>> info() {
return commandManager.submitNewCommand(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@ public interface ConnectionManagementClusterCommands {
*/
CompletableFuture<String> ping(String message);

/**
* Pings the Redis server.<br>
* The command will be routed to all primary nodes.
*
* @see <a href="https://redis.io/commands/ping/">redis.io</a> for details.
* @param message The server will respond with a copy of the message.
* @return <code>GlideString</code> with a copy of the argument <code>message</code>.
* @example
* <pre>{@code
* GlideString payload = clusterClient.ping(gs("GLIDE")).get();
* assert payload.equals(gs("GLIDE"));
* }</pre>
*/
CompletableFuture<GlideString> ping(GlideString message);

/**
* Pings the Redis server.
*
Expand Down Expand Up @@ -73,6 +88,22 @@ public interface ConnectionManagementClusterCommands {
*/
CompletableFuture<String> ping(String message, Route route);

/**
* Pings the Redis server.
*
* @see <a href="https://redis.io/commands/ping/">redis.io</a> for details.
* @param message The ping argument that will be returned.
* @param route Specifies the routing configuration for the command. The client will route the
* command to the nodes defined by <code>route</code>.
* @return <code>GlideString</code> with a copy of the argument <code>message</code>.
* @example
* <pre>{@code
* GlideString payload = clusterClient.ping(gs("GLIDE"), RANDOM).get();
* assert payload.equals(gs("GLIDE"));
* }</pre>
*/
CompletableFuture<GlideString> ping(GlideString message, Route route);

/**
* Gets the current connection id.<br>
* The command will be routed to a random node.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ public interface ConnectionManagementCommands {
*/
CompletableFuture<String> ping(String message);

/**
* Pings the Redis server.
*
* @see <a href="https://redis.io/commands/ping/">redis.io</a> for details.
* @param message The server will respond with a copy of the message.
* @return <code>GlideString</code> with a copy of the argument <code>message</code>.
* @example
* <pre>{@code
* GlideString payload = client.ping(gs("GLIDE")).get();
* assert payload.equals(gs("GLIDE"));
* }</pre>
*/
CompletableFuture<GlideString> ping(GlideString message);

/**
* Gets the current connection id.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,22 @@ CompletableFuture<Boolean> pexpireAt(
*/
CompletableFuture<Long> touch(String[] keys);

/**
* Updates the last access time of specified <code>keys</code>.
*
* @apiNote When in cluster mode, the command may route to multiple nodes when <code>keys</code>
* map to different hash slots.
* @see <a href="https://redis.io/commands/touch/">redis.io</a> for details.
* @param keys The keys to update last access time.
* @return The number of keys that were updated.
* @example
* <pre>{@code
* Long payload = client.touch(new GlideString[] {gs("myKey1"), gs("myKey2"), gs("nonExistentKey")}).get();
* assert payload == 2L; // Last access time of 2 keys has been updated.
* }</pre>
*/
CompletableFuture<Long> touch(GlideString[] keys);

/**
* Copies the value stored at the <code>source</code> to the <code>destination</code> key if the
* <code>destination</code> key does not yet exist.
Expand Down
39 changes: 39 additions & 0 deletions java/client/src/main/java/glide/api/commands/SetBaseCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,24 @@ public interface SetBaseCommands {
*/
CompletableFuture<Long> sunionstore(String destination, String[] keys);

/**
* Stores the members of the union of all given sets specified by <code>keys</code> into a new set
* at <code>destination</code>.
*
* @apiNote When in cluster mode, <code>destination</code> and all <code>keys</code> must map to
* the same hash slot.
* @see <a href="https://redis.io/commands/sunionstore/">redis.io</a> for details.
* @param destination The key of the destination set.
* @param keys The keys from which to retrieve the set members.
* @return The number of elements in the resulting set.
* @example
* <pre>{@code
* Long length = client.sunionstore(gs("mySet"), new GlideString[] { gs("set1"), gs("set2") }).get();
* assert length == 5L;
* }</pre>
*/
CompletableFuture<Long> sunionstore(GlideString destination, GlideString[] keys);

/**
* Returns a random element from the set value stored at <code>key</code>.
*
Expand Down Expand Up @@ -640,6 +658,27 @@ public interface SetBaseCommands {
*/
CompletableFuture<Set<String>> sunion(String[] keys);

/**
* Gets the union of all the given sets.
*
* @apiNote When in cluster mode, all <code>keys</code> must map to the same hash slot.
* @see <a href="https://valkey.io/commands/sunion">valkey.io</a> for details.
* @param keys The keys of the sets.
* @return A set of members which are present in at least one of the given sets. If none of the
* sets exist, an empty set will be returned.
* @example
* <pre>{@code
* assert client.sadd(gs("my_set1"), new GlideString[]{gs("member1"), gs("member2")}).get() == 2;
* assert client.sadd(gs("my_set2"), new GlideString[]{gs("member2"), gs("member3")}).get() == 2;
* Set<GlideString> result = client.sunion(new GlideString[] {gs("my_set1"), gs("my_set2")}).get();
* assertEquals(Set.of(gs("member1"), gs("member2"), gs("member3")), result);
*
* result = client.sunion(new GlideString[] {gs("my_set1"), gs("non_existent_set")}).get();
* assertEquals(Set.of(gs("member1"), gs("member2")), result);
* }</pre>
*/
CompletableFuture<Set<GlideString>> sunion(GlideString[] keys);

/**
* Iterates incrementally over a set.
*
Expand Down
91 changes: 91 additions & 0 deletions java/client/src/test/java/glide/api/RedisClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,28 @@ public void ping_with_message_returns_success() {
assertEquals(message, pong);
}

@SneakyThrows
@Test
public void ping_binary_with_message_returns_success() {
// setup
GlideString message = gs("RETURN OF THE PONG");
GlideString[] arguments = new GlideString[] {message};
CompletableFuture<GlideString> testResponse = new CompletableFuture<>();
testResponse.complete(message);

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

// exercise
CompletableFuture<GlideString> response = service.ping(message);
GlideString pong = response.get();

// verify
assertEquals(testResponse, response);
assertEquals(message, pong);
}

@SneakyThrows
@Test
public void select_returns_success() {
Expand Down Expand Up @@ -3934,6 +3956,31 @@ public void sunionstore_returns_success() {
assertEquals(value, payload);
}

@SneakyThrows
@Test
public void sunionstore_binary_returns_success() {
// setup
GlideString destination = gs("key");
GlideString[] keys = new GlideString[] {gs("set1"), gs("set2")};
GlideString[] args = new GlideString[] {gs("key"), gs("set1"), gs("set2")};
Long value = 2L;

CompletableFuture<Long> testResponse = new CompletableFuture<>();
testResponse.complete(value);

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

// exercise
CompletableFuture<Long> response = service.sunionstore(destination, keys);
Long payload = response.get();

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

@SneakyThrows
@Test
public void zadd_noOptions_returns_success() {
Expand Down Expand Up @@ -8045,6 +8092,28 @@ public void touch_returns_success() {
assertEquals(value, payload);
}

@SneakyThrows
@Test
public void touch_binary_returns_success() {
// setup
GlideString[] keys = new GlideString[] {gs("testKey1"), gs("testKey2")};
Long value = 2L;
CompletableFuture<Long> testResponse = new CompletableFuture<>();
testResponse.complete(value);

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

// exercise
CompletableFuture<Long> response = service.touch(keys);
Long payload = response.get();

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

@SneakyThrows
@Test
public void geoadd_returns_success() {
Expand Down Expand Up @@ -10428,6 +10497,28 @@ public void sunion_returns_success() {
assertEquals(value, payload);
}

@SneakyThrows
@Test
public void sunion_binary_returns_success() {
// setup
GlideString[] keys = new GlideString[] {gs("key1"), gs("key2")};
Set<GlideString> value = Set.of(gs("1"), gs("2"));
CompletableFuture<Set<GlideString>> testResponse = new CompletableFuture<>();
testResponse.complete(value);

// match on protobuf request
when(commandManager.<Set<GlideString>>submitNewCommand(eq(SUnion), eq(keys), any()))
.thenReturn(testResponse);

// exercise
CompletableFuture<Set<GlideString>> response = service.sunion(keys);
Set<GlideString> payload = response.get();

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

@SneakyThrows
@Test
public void dump_returns_success() {
Expand Down
46 changes: 46 additions & 0 deletions java/client/src/test/java/glide/api/RedisClusterClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,28 @@ public void ping_with_message_returns_success() {
assertEquals(message, pong);
}

@SneakyThrows
@Test
public void ping_binary_with_message_returns_success() {
// setup
GlideString message = gs("RETURN OF THE PONG");
GlideString[] arguments = new GlideString[] {message};
CompletableFuture<GlideString> testResponse = new CompletableFuture<>();
testResponse.complete(message);

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

// exercise
CompletableFuture<GlideString> response = service.ping(message);
GlideString pong = response.get();

// verify
assertEquals(testResponse, response);
assertEquals(message, pong);
}

@SneakyThrows
@Test
public void ping_with_route_returns_success() {
Expand Down Expand Up @@ -332,6 +354,30 @@ public void ping_with_message_with_route_returns_success() {
assertEquals(message, pong);
}

@SneakyThrows
@Test
public void ping_binary_with_message_with_route_returns_success() {
// setup
GlideString message = gs("RETURN OF THE PONG");
GlideString[] arguments = new GlideString[] {message};
CompletableFuture<GlideString> testResponse = new CompletableFuture<>();
testResponse.complete(message);

Route route = ALL_PRIMARIES;

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

// exercise
CompletableFuture<GlideString> response = service.ping(message, route);
GlideString pong = response.get();

// verify
assertEquals(testResponse, response);
assertEquals(message, pong);
}

@SneakyThrows
@Test
public void echo_returns_success() {
Expand Down
Loading

0 comments on commit e2aafd7

Please sign in to comment.