Skip to content

Commit

Permalink
Java: fix javadoc and cluster implemetation for INFO command (valke…
Browse files Browse the repository at this point in the history
…y-io#960)

* Minor javadoc updated for `info` command.

Signed-off-by: Yury-Fridlyand <[email protected]>

---------

Signed-off-by: Yury-Fridlyand <[email protected]>
  • Loading branch information
Yury-Fridlyand authored Feb 16, 2024
1 parent 10cdf60 commit fa625a9
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 36 deletions.
22 changes: 15 additions & 7 deletions java/client/src/main/java/glide/api/BaseClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import glide.managers.BaseCommandResponseResolver;
import glide.managers.CommandManager;
import glide.managers.ConnectionManager;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
Expand Down Expand Up @@ -121,7 +122,7 @@ protected static CommandManager buildCommandManager(ChannelHandler channelHandle
* @throws RedisException on a type mismatch
*/
@SuppressWarnings("unchecked")
private <T> T handleRedisResponse(Class<T> classType, boolean isNullable, Response response)
protected <T> T handleRedisResponse(Class<T> classType, boolean isNullable, Response response)
throws RedisException {
Object value =
new BaseCommandResponseResolver(RedisValueResolver::valueFromPointer).apply(response);
Expand All @@ -139,10 +140,6 @@ private <T> T handleRedisResponse(Class<T> classType, boolean isNullable, Respon
+ classType.getSimpleName());
}

protected Object handleObjectResponse(Response response) throws RedisException {
return handleRedisResponse(Object.class, false, response);
}

protected Object handleObjectOrNullResponse(Response response) throws RedisException {
return handleRedisResponse(Object.class, true, response);
}
Expand All @@ -159,11 +156,22 @@ protected Long handleLongResponse(Response response) throws RedisException {
return handleRedisResponse(Long.class, false, response);
}

protected Object[] handleArrayResponse(Response response) {
protected Object[] handleArrayResponse(Response response) throws RedisException {
return handleRedisResponse(Object[].class, true, response);
}

protected Set<String> handleSetResponse(Response response) {
/**
* @param response A Protobuf response
* @return A map of <code>String</code> to <code>V</code>
* @param <V> Value type, could be even map too
*/
@SuppressWarnings("unchecked") // raw Map cast to Map<String, V>
protected <V> Map<String, V> handleMapResponse(Response response) throws RedisException {
return handleRedisResponse(Map.class, false, response);
}

@SuppressWarnings("unchecked") // raw Set cast to Set<String>
protected Set<String> handleSetResponse(Response response) throws RedisException {
return handleRedisResponse(Set.class, false, response);
}

Expand Down
20 changes: 16 additions & 4 deletions java/client/src/main/java/glide/api/RedisClusterClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,24 +99,36 @@ public CompletableFuture<String> ping(@NonNull String str, @NonNull Route route)
@Override
public CompletableFuture<ClusterValue<String>> info() {
return commandManager.submitNewCommand(
Info, new String[0], response -> ClusterValue.of(handleObjectResponse(response)));
Info, new String[0], response -> ClusterValue.of(handleMapResponse(response)));
}

public CompletableFuture<ClusterValue<String>> info(@NonNull Route route) {
return commandManager.submitNewCommand(
Info, new String[0], route, response -> ClusterValue.of(handleObjectResponse(response)));
Info,
new String[0],
route,
response ->
route.isSingleNodeRoute()
? ClusterValue.of(handleStringResponse(response))
: ClusterValue.of(handleMapResponse(response)));
}

@Override
public CompletableFuture<ClusterValue<String>> info(@NonNull InfoOptions options) {
return commandManager.submitNewCommand(
Info, options.toArgs(), response -> ClusterValue.of(handleObjectResponse(response)));
Info, options.toArgs(), response -> ClusterValue.of(handleMapResponse(response)));
}

@Override
public CompletableFuture<ClusterValue<String>> info(
@NonNull InfoOptions options, @NonNull Route route) {
return commandManager.submitNewCommand(
Info, options.toArgs(), route, response -> ClusterValue.of(handleObjectResponse(response)));
Info,
options.toArgs(),
route,
response ->
route.isSingleNodeRoute()
? ClusterValue.of(handleStringResponse(response))
: ClusterValue.of(handleMapResponse(response)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import glide.api.models.ClusterValue;
import glide.api.models.commands.InfoOptions;
import glide.api.models.commands.InfoOptions.Section;
import glide.api.models.configuration.RequestRoutingConfiguration.Route;
import java.util.concurrent.CompletableFuture;

Expand All @@ -14,11 +15,10 @@
public interface ServerManagementClusterCommands {

/**
* Get information and statistics about the Redis server. DEFAULT option is assumed. The command
* will be routed to all primaries.
* Get information and statistics about the Redis server using the {@link Section#DEFAULT} option.
* The command will be routed to all primary nodes.
*
* @see <a href="https://redis.io/commands/info/">redis.io</a> for details. {@link
* InfoOptions.Section#DEFAULT} option is assumed.
* @see <a href="https://redis.io/commands/info/">redis.io</a> for details.
* @return Response from Redis cluster with a <code>Map{@literal <String, String>}</code> with
* each address as the key and its corresponding value is the information for the node.
* @example
Expand All @@ -29,7 +29,8 @@ public interface ServerManagementClusterCommands {
CompletableFuture<ClusterValue<String>> info();

/**
* Get information and statistics about the Redis server. DEFAULT option is assumed
* Get information and statistics about the Redis server. If no argument is provided, so the
* {@link Section#DEFAULT} option is assumed.
*
* @see <a href="https://redis.io/commands/info/">redis.io</a> for details.
* @param route Routing configuration for the command. Client will route the command to the nodes
Expand All @@ -43,10 +44,10 @@ public interface ServerManagementClusterCommands {

/**
* Get information and statistics about the Redis server. The command will be routed to all
* primaries.
* primary nodes.
*
* @see <a href="https://redis.io/commands/info/">redis.io</a> for details.
* @param options - A list of {@link InfoOptions.Section} values specifying which sections of
* @param options A list of {@link InfoOptions.Section} values specifying which sections of
* information to retrieve. When no parameter is provided, the {@link
* InfoOptions.Section#DEFAULT} option is assumed.
* @return Response from Redis cluster with a <code>Map{@literal <String, String>}</code> with
Expand All @@ -59,7 +60,7 @@ public interface ServerManagementClusterCommands {
* Get information and statistics about the Redis server.
*
* @see <a href="https://redis.io/commands/info/">redis.io</a> for details.
* @param options - A list of {@link InfoOptions.Section} values specifying which sections of
* @param options A list of {@link InfoOptions.Section} values specifying which sections of
* information to retrieve. When no parameter is provided, the {@link
* InfoOptions.Section#DEFAULT} option is assumed.
* @param route Routing configuration for the command. Client will route the command to the nodes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
public interface ServerManagementCommands {

/**
* Get information and statistics about the Redis server. No argument is provided, so the {@link
* Section#DEFAULT} option is assumed.
* Get information and statistics about the Redis server using the {@link Section#DEFAULT} option.
*
* @see <a href="https://redis.io/commands/info/">redis.io</a> for details.
* @return Response from Redis containing a <code>String</code> with the information for the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ public T ping(String msg) {
}

/**
* Get information and statistics about the Redis server. No argument is provided, so the {@link
* Section#DEFAULT} option is assumed.
* Get information and statistics about the Redis server using the {@link Section#DEFAULT} option.
*
* @see <a href="https://redis.io/commands/info/">redis.io</a> for details.
* @return A response from Redis with a <code>String</code>.
Expand Down
70 changes: 59 additions & 11 deletions java/client/src/test/java/glide/api/RedisClusterClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,7 @@ public void custom_command_returns_single_value() {
var client = new TestClient(commandManager, "TEST");

var value = client.customCommand(TEST_ARGS).get();
assertAll(
() -> assertTrue(value.hasSingleData()),
() -> assertEquals("TEST", value.getSingleValue()));
assertEquals("TEST", value.getSingleValue());
}

@Test
Expand All @@ -68,8 +66,7 @@ public void custom_command_returns_multi_value() {
var client = new TestClient(commandManager, data);

var value = client.customCommand(TEST_ARGS).get();
assertAll(
() -> assertTrue(value.hasMultiData()), () -> assertEquals(data, value.getMultiValue()));
assertEquals(data, value.getMultiValue());
}

@Test
Expand All @@ -82,8 +79,7 @@ public void custom_command_with_single_node_route_returns_single_value() {
var client = new TestClient(commandManager, data);

var value = client.customCommand(TEST_ARGS, RANDOM).get();
assertAll(
() -> assertTrue(value.hasSingleData()), () -> assertEquals(data, value.getSingleValue()));
assertEquals(data, value.getSingleValue());
}

@Test
Expand All @@ -95,8 +91,7 @@ public void custom_command_with_multi_node_route_returns_multi_value() {
var client = new TestClient(commandManager, data);

var value = client.customCommand(TEST_ARGS, ALL_NODES).get();
assertAll(
() -> assertTrue(value.hasMultiData()), () -> assertEquals(data, value.getMultiValue()));
assertEquals(data, value.getMultiValue());
}

private static class TestClient extends RedisClusterClient {
Expand All @@ -108,9 +103,10 @@ public TestClient(CommandManager commandManager, Object objectToReturn) {
object = objectToReturn;
}

@SuppressWarnings("unchecked")
@Override
protected Object handleObjectOrNullResponse(Response response) {
return object;
protected <T> T handleRedisResponse(Class<T> classType, boolean isNullable, Response response) {
return (T) object;
}
}

Expand Down Expand Up @@ -251,4 +247,56 @@ public void info_with_route_with_infoOptions_returns_string() {
assertEquals("addr1 result", clusterMap.get("addr1"));
assertEquals("addr2 result", clusterMap.get("addr2"));
}

@Test
@SneakyThrows
public void info_with_single_node_route_returns_single_value() {
var commandManager = new TestCommandManager(null);

var data = "info string";
var client = new TestClient(commandManager, data);

var value = client.info(RANDOM).get();
assertAll(
() -> assertTrue(value.hasSingleData()), () -> assertEquals(data, value.getSingleValue()));
}

@Test
@SneakyThrows
public void info_with_multi_node_route_returns_multi_value() {
var commandManager = new TestCommandManager(null);

var data = Map.of("key1", "value1", "key2", "value2");
var client = new TestClient(commandManager, data);

var value = client.info(ALL_NODES).get();
assertAll(
() -> assertTrue(value.hasMultiData()), () -> assertEquals(data, value.getMultiValue()));
}

@Test
@SneakyThrows
public void info_with_options_and_single_node_route_returns_single_value() {
var commandManager = new TestCommandManager(null);

var data = "info string";
var client = new TestClient(commandManager, data);

var value = client.info(InfoOptions.builder().build(), RANDOM).get();
assertAll(
() -> assertTrue(value.hasSingleData()), () -> assertEquals(data, value.getSingleValue()));
}

@Test
@SneakyThrows
public void info_with_options_and_multi_node_route_returns_multi_value() {
var commandManager = new TestCommandManager(null);

var data = Map.of("key1", "value1", "key2", "value2");
var client = new TestClient(commandManager, data);

var value = client.info(InfoOptions.builder().build(), ALL_NODES).get();
assertAll(
() -> assertTrue(value.hasMultiData()), () -> assertEquals(data, value.getMultiValue()));
}
}
35 changes: 33 additions & 2 deletions java/integTest/src/test/java/glide/cluster/CommandTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public void info_without_options() {

@Test
@SneakyThrows
public void info_with_route() {
public void info_with_single_node_route() {
ClusterValue<String> data = clusterClient.info(RANDOM).get();
assertTrue(data.hasSingleData());
String infoData = data.getSingleValue();
Expand All @@ -167,6 +167,18 @@ public void info_with_route() {
}
}

@Test
@SneakyThrows
public void info_with_multi_node_route() {
ClusterValue<String> data = clusterClient.info(ALL_NODES).get();
assertTrue(data.hasMultiData());
for (String info : data.getMultiValue().values()) {
for (String section : DEFAULT_INFO_SECTIONS) {
assertTrue(info.contains("# " + section), "Section " + section + " is missing");
}
}
}

@Test
@SneakyThrows
public void info_with_multiple_options() {
Expand Down Expand Up @@ -200,7 +212,7 @@ public void info_with_everything_option() {

@Test
@SneakyThrows
public void info_with_routing_and_options() {
public void info_with_single_node_route_and_options() {
ClusterValue<Object> slotData =
clusterClient.customCommand(new String[] {"cluster", "slots"}).get();

Expand Down Expand Up @@ -229,4 +241,23 @@ public void info_with_routing_and_options() {
"Section " + section + " is missing");
}
}

@Test
@SneakyThrows
public void info_with_multi_node_route_and_options() {
InfoOptions.InfoOptionsBuilder builder = InfoOptions.builder().section(CLIENTS);
if (REDIS_VERSION.feature() >= 7) {
builder.section(COMMANDSTATS).section(REPLICATION);
}
InfoOptions options = builder.build();
ClusterValue<String> data = clusterClient.info(options, ALL_NODES).get();

for (String info : data.getMultiValue().values()) {
for (String section : options.toArgs()) {
assertTrue(
info.toLowerCase().contains("# " + section.toLowerCase()),
"Section " + section + " is missing");
}
}
}
}

0 comments on commit fa625a9

Please sign in to comment.