Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java: add RANDOMKEY #1576

Merged
merged 20 commits into from
Jun 19, 2024
1 change: 1 addition & 0 deletions glide-core/src/protobuf/redis_request.proto
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ enum RequestType {
SUnion = 186;
Publish = 187;
SPublish = 188;
RandomKey = 191;
}

message Command {
Expand Down
3 changes: 3 additions & 0 deletions glide-core/src/request_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ pub enum RequestType {
SUnion = 186,
Publish = 187,
SPublish = 188,
RandomKey = 191,
}

fn get_two_word_command(first: &str, second: &str) -> Cmd {
Expand Down Expand Up @@ -395,6 +396,7 @@ impl From<::protobuf::EnumOrUnknown<ProtobufRequestType>> for RequestType {
ProtobufRequestType::GeoSearchStore => RequestType::GeoSearchStore,
ProtobufRequestType::Publish => RequestType::Publish,
ProtobufRequestType::SPublish => RequestType::SPublish,
ProtobufRequestType::RandomKey => RequestType::RandomKey,
}
}
}
Expand Down Expand Up @@ -590,6 +592,7 @@ impl RequestType {
RequestType::GeoSearchStore => Some(cmd("GEOSEARCHSTORE")),
RequestType::Publish => Some(cmd("PUBLISH")),
RequestType::SPublish => Some(cmd("SPUBLISH")),
RequestType::RandomKey => Some(cmd("RANDOMKEY")),
}
}
}
7 changes: 7 additions & 0 deletions java/client/src/main/java/glide/api/RedisClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.Lolwut;
import static redis_request.RedisRequestOuterClass.RequestType.Move;
import static redis_request.RedisRequestOuterClass.RequestType.Ping;
import static redis_request.RedisRequestOuterClass.RequestType.RandomKey;
import static redis_request.RedisRequestOuterClass.RequestType.Select;
import static redis_request.RedisRequestOuterClass.RequestType.Time;
import static redis_request.RedisRequestOuterClass.RequestType.UnWatch;
Expand Down Expand Up @@ -305,4 +306,10 @@ public CompletableFuture<Map<String, Map<String, Object>>> functionStats() {
public CompletableFuture<String> unwatch() {
return commandManager.submitNewCommand(UnWatch, new String[0], this::handleStringResponse);
}

@Override
public CompletableFuture<String> randomKey() {
return commandManager.submitNewCommand(
RandomKey, new String[0], this::handleStringOrNullResponse);
}
}
13 changes: 13 additions & 0 deletions java/client/src/main/java/glide/api/RedisClusterClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.LastSave;
import static redis_request.RedisRequestOuterClass.RequestType.Lolwut;
import static redis_request.RedisRequestOuterClass.RequestType.Ping;
import static redis_request.RedisRequestOuterClass.RequestType.RandomKey;
import static redis_request.RedisRequestOuterClass.RequestType.Time;
import static redis_request.RedisRequestOuterClass.RequestType.UnWatch;

Expand Down Expand Up @@ -665,4 +666,16 @@ public CompletableFuture<String> unwatch(@NonNull Route route) {
public CompletableFuture<String> unwatch() {
return commandManager.submitNewCommand(UnWatch, new String[0], this::handleStringResponse);
}

@Override
public CompletableFuture<String> randomKey(@NonNull Route route) {
return commandManager.submitNewCommand(
RandomKey, new String[0], route, this::handleStringOrNullResponse);
}

@Override
public CompletableFuture<String> randomKey() {
return commandManager.submitNewCommand(
RandomKey, new String[0], this::handleStringOrNullResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,40 @@ public interface GenericClusterCommands {
* }</pre>
*/
CompletableFuture<Object[]> exec(ClusterTransaction transaction, SingleNodeRoute route);

/**
* Returns a random key.
*
* @see <a href="https://redis.io/docs/latest/commands/randomkey/">redis.io</a> for details.
* @param route Specifies the routing configuration for the command. The client will route the
* command to the nodes defined by <code>route</code>, and will return the first successful
* result.
* @return A random <code>key</code> from the database.
* @example
* <pre>{@code
* String value = client.set("key", "value").get();
* String value_1 = client.set("key1", "value_1").get();
* String key = client.randomKey(RANDOM).get();
* System.out.println("The random key is: " + key);
* // The value of key is either "key" or "key1"
* }</pre>
*/
CompletableFuture<String> randomKey(Route route);

/**
* Returns a random key.<br>
* The command will be routed to all primary nodes, and will return the first successful result.
*
* @see <a href="https://redis.io/docs/latest/commands/randomkey/">redis.io</a> for details.
* @return A random <code>key</code> from the database.
* @example
* <pre>{@code
* String value = client.set("key", "value").get();
* String value_1 = client.set("key1", "value_1").get();
* String key = client.randomKey().get();
* System.out.println("The random key is: " + key);
* // The value of key is either "key" or "key1"
* }</pre>
*/
CompletableFuture<String> randomKey();
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,20 @@ CompletableFuture<Boolean> copy(
* }</pre>
*/
CompletableFuture<Boolean> copy(String source, String destination, long destinationDB);

/**
* Returns a random key from currently selected database.
*
* @see <a href="https://redis.io/docs/latest/commands/randomkey/">redis.io</a> for details.
* @return A random <code>key</code> from the database.
* @example
* <pre>{@code
* String value = client.set("key", "value").get();
* String value_1 = client.set("key1", "value_1").get();
* String key = client.randomKey().get();
* System.out.println("The random key is: " + key);
* // The value of key is either "key" or "key1"
* }</pre>
*/
CompletableFuture<String> randomKey();
}
12 changes: 12 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 @@ -119,6 +119,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.RPop;
import static redis_request.RedisRequestOuterClass.RequestType.RPush;
import static redis_request.RedisRequestOuterClass.RequestType.RPushX;
import static redis_request.RedisRequestOuterClass.RequestType.RandomKey;
import static redis_request.RedisRequestOuterClass.RequestType.Rename;
import static redis_request.RedisRequestOuterClass.RequestType.RenameNX;
import static redis_request.RedisRequestOuterClass.RequestType.SAdd;
Expand Down Expand Up @@ -3188,6 +3189,17 @@ public T type(@NonNull String key) {
return getThis();
}

/**
* Returns a random key from the currently selected database. *
*
* @see <a href="https://redis.io/docs/latest/commands/randomkey/">redis.io</a> for details.
* @return Command Response - A random <code>key</code> from the database.
*/
public T randomKey() {
protobufTransaction.addCommands(buildCommand(RandomKey));
return getThis();
}

/**
* Renames <code>key</code> to <code>newKey</code>.<br>
* If <code>newKey</code> already exists it is overwritten.
Expand Down
18 changes: 18 additions & 0 deletions java/client/src/test/java/glide/api/RedisClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.RPop;
import static redis_request.RedisRequestOuterClass.RequestType.RPush;
import static redis_request.RedisRequestOuterClass.RequestType.RPushX;
import static redis_request.RedisRequestOuterClass.RequestType.RandomKey;
import static redis_request.RedisRequestOuterClass.RequestType.Rename;
import static redis_request.RedisRequestOuterClass.RequestType.RenameNX;
import static redis_request.RedisRequestOuterClass.RequestType.SAdd;
Expand Down Expand Up @@ -4478,6 +4479,23 @@ public void type_returns_success() {
assertEquals(value, payload);
}

@SneakyThrows
@Test
public void randomKey() {
// setup
String key1 = "key1";
CompletableFuture<String> testResponse = new CompletableFuture<>();
testResponse.complete(key1);

// match on protobuf request
when(commandManager.<String>submitNewCommand(eq(RandomKey), eq(new String[0]), any()))
.thenReturn(testResponse);
CompletableFuture<String> response = service.randomKey();

// verify
assertEquals(testResponse, response);
}

@SneakyThrows
@Test
public void rename() {
Expand Down
37 changes: 37 additions & 0 deletions java/client/src/test/java/glide/api/RedisClusterClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.LastSave;
import static redis_request.RedisRequestOuterClass.RequestType.Lolwut;
import static redis_request.RedisRequestOuterClass.RequestType.Ping;
import static redis_request.RedisRequestOuterClass.RequestType.RandomKey;
import static redis_request.RedisRequestOuterClass.RequestType.Time;
import static redis_request.RedisRequestOuterClass.RequestType.UnWatch;

Expand Down Expand Up @@ -1778,4 +1779,40 @@ public void functionStats_with_route_returns_success() {
assertEquals(testResponse, response);
assertEquals(value, payload);
}

@SneakyThrows
@Test
public void randomKey_with_route() {
// setup
String key1 = "key1";
CompletableFuture<String> testResponse = new CompletableFuture<>();
testResponse.complete(key1);
Route route = ALL_NODES;

// match on protobuf request
when(commandManager.<String>submitNewCommand(
eq(RandomKey), eq(new String[0]), eq(route), any()))
.thenReturn(testResponse);
CompletableFuture<String> response = service.randomKey(route);

// verify
assertEquals(testResponse, response);
}

@SneakyThrows
@Test
public void randomKey() {
// setup
String key1 = "key1";
CompletableFuture<String> testResponse = new CompletableFuture<>();
testResponse.complete(key1);

// match on protobuf request
when(commandManager.<String>submitNewCommand(eq(RandomKey), eq(new String[0]), any()))
.thenReturn(testResponse);
CompletableFuture<String> response = service.randomKey();

// verify
assertEquals(testResponse, response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.RPop;
import static redis_request.RedisRequestOuterClass.RequestType.RPush;
import static redis_request.RedisRequestOuterClass.RequestType.RPushX;
import static redis_request.RedisRequestOuterClass.RequestType.RandomKey;
import static redis_request.RedisRequestOuterClass.RequestType.Rename;
import static redis_request.RedisRequestOuterClass.RequestType.RenameNX;
import static redis_request.RedisRequestOuterClass.RequestType.SAdd;
Expand Down Expand Up @@ -812,6 +813,9 @@ InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3, false), new Limit(1, 2)),
transaction.type("key");
results.add(Pair.of(Type, buildArgs("key")));

transaction.randomKey();
results.add(Pair.of(RandomKey, buildArgs()));

transaction.rename("key", "newKey");
results.add(Pair.of(Rename, buildArgs("key", "newKey")));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,9 @@ private static Object[] stringCommands(BaseTransaction<?> transaction) {
String stringKey8 = "{StringKey}-8-" + UUID.randomUUID();

transaction
.flushall()
.set(stringKey1, value1)
.randomKey()
.get(stringKey1)
.getdel(stringKey1)
.set(stringKey2, value2, SetOptions.builder().returnOldValue(true).build())
Expand Down Expand Up @@ -243,7 +245,9 @@ private static Object[] stringCommands(BaseTransaction<?> transaction) {

var expectedResults =
new Object[] {
OK, // flushall()
OK, // set(stringKey1, value1)
stringKey1, // randomKey()
value1, // get(stringKey1)
value1, // getdel(stringKey1)
null, // set(stringKey2, value2, returnOldValue(true))
Expand Down
23 changes: 23 additions & 0 deletions java/integTest/src/test/java/glide/cluster/CommandTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -1545,4 +1545,27 @@ public void functionStats_with_route(boolean singleNodeRoute) {
}
}
}

@Test
@SneakyThrows
public void randomKey() {
String key1 = "{key}" + UUID.randomUUID();
String key2 = "{key}" + UUID.randomUUID();

assertEquals(OK, clusterClient.set(key1, "a").get());
assertEquals(OK, clusterClient.set(key2, "b").get());

String randomKey = clusterClient.randomKey().get();
assertEquals(1L, clusterClient.exists(new String[] {randomKey}).get());
acarbonetto marked this conversation as resolved.
Show resolved Hide resolved

String randomKeyPrimaries = clusterClient.randomKey(ALL_PRIMARIES).get();
assertEquals(1L, clusterClient.exists(new String[] {randomKeyPrimaries}).get());

// no keys in database
assertEquals(OK, clusterClient.flushall(SYNC).get());

// TODO: returns a ResponseError but expecting null
// uncomment when this is completed: https://github.com/amazon-contributing/redis-rs/pull/153
// assertNull(clusterClient.randomKey().get());
}
}
17 changes: 17 additions & 0 deletions java/integTest/src/test/java/glide/standalone/CommandTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -690,4 +690,21 @@ public void functionStats() {
response = regularClient.functionStats().get();
checkFunctionStatsResponse(response, new String[0], 0, 0);
}

@SneakyThrows
@Test
public void randomkey() {
String key1 = "{key}" + UUID.randomUUID();
String key2 = "{key}" + UUID.randomUUID();

assertEquals(OK, regularClient.set(key1, "a").get());
assertEquals(OK, regularClient.set(key2, "b").get());

String randomKey = regularClient.randomKey().get();
assertEquals(1L, regularClient.exists(new String[] {randomKey}).get());

// no keys in database
assertEquals(OK, regularClient.flushall().get());
assertNull(regularClient.randomKey().get());
}
}
Loading