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

Added part of the 'String Commands' group to RedisClient as specified on the official Redis website. #68

Closed
54 changes: 54 additions & 0 deletions java/client/src/main/java/glide/api/BaseClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,60 @@ protected static String handleStringResponse(Response response) {
+ " expected String");
}

/**
* Extracts the response value from the Redis response and either throws an exception or returns
* the value as a Long.
*
* @param response Redis protobuf message
* @return Response as a Long
*/
protected static Long handleLongResponse(Response response) {
Object value = handleObjectResponse(response);
if (value instanceof Long) {
Yury-Fridlyand marked this conversation as resolved.
Show resolved Hide resolved
return (Long) value;
}
throw new RedisException(
"Unexpected return type from Redis: got "
+ value.getClass().getSimpleName()
+ " expected Long");
}

/**
* Extracts the response value from the Redis response and either throws an exception or returns
* the value as a Double.
*
* @param response Redis protobuf message
* @return Response as a Double
*/
protected static Double handleDoubleResponse(Response response) {
Object value = handleObjectResponse(response);
if (value instanceof Double) {
return (Double) value;
}
throw new RedisException(
"Unexpected return type from Redis: got "
+ value.getClass().getSimpleName()
+ " expected Double");
}

/**
* Extracts the response value from the Redis response and either throws an exception or returns
* the value as an Object Array.
*
* @param response Redis protobuf message
* @return Response as an Object Array
*/
protected static Object[] handleObjectArrayResponse(Response response) {
Object value = handleObjectResponse(response);
if (value instanceof Object[]) {
return (Object[]) value;
}
throw new RedisException(
"Unexpected return type from Redis: got "
+ value.getClass().getSimpleName()
+ " expected Object Array");
}

/**
* Extracts the response value from the Redis response and either throws an exception or returns
* the * value as a HashMap
Expand Down
174 changes: 158 additions & 16 deletions java/client/src/main/java/glide/api/RedisClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import glide.managers.CommandManager;
import glide.managers.ConnectionManager;
import glide.managers.models.Command;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
Expand All @@ -29,8 +31,8 @@ public class RedisClient extends BaseClient
/**
* Request an async (non-blocking) Redis client in Standalone mode.
*
* @param config - Redis Client Configuration
* @return a Future to connect and return a RedisClient
* @param config Redis Client Configuration
* @return A Future to connect and return a RedisClient
*/
public static CompletableFuture<RedisClient> CreateClient(RedisClientConfiguration config) {
try {
Expand Down Expand Up @@ -79,8 +81,8 @@ protected RedisClient(ConnectionManager connectionManager, CommandManager comman
* Object result = client.customCommand(new String[]{"CLIENT","LIST","TYPE", "PUBSUB"}).get();
* </pre>
*
* @param args arguments for the custom command
* @return a CompletableFuture with response result from Redis
* @param args Arguments for the custom command
* @return A CompletableFuture with response result from Redis

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed, you can simplify that - here and for all other functions (except CreateClient I think)

Suggested change
* @return A CompletableFuture with response result from Redis
* @return A response from Redis

*/
public CompletableFuture<Object> customCommand(String[] args) {
Command command =
Expand All @@ -92,7 +94,7 @@ public CompletableFuture<Object> customCommand(String[] args) {
* Ping the Redis server.
*
* @see <a href="https://redis.io/commands/ping/">redis.io</a> for details.
* @returns the String "PONG"
* @return The String "PONG"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @return The String "PONG"
* @return A server response

*/
@Override
public CompletableFuture<String> ping() {
Expand All @@ -104,8 +106,8 @@ public CompletableFuture<String> ping() {
* Ping the Redis server.
*
* @see <a href="https://redis.io/commands/ping/">redis.io</a> for details.
* @param msg - the ping argument that will be returned.
* @returns return a copy of the argument.
* @param msg The ping argument that will be returned.
* @return Return a copy of the argument.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Seems like in the other docs we don't do "@return Return"

Suggested change
* @return Return a copy of the argument.
* @return A copy of the argument.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @return Return a copy of the argument.
* @return A server response

*/
@Override
public CompletableFuture<String> ping(String msg) {
Expand Down Expand Up @@ -133,7 +135,7 @@ public CompletableFuture<Map> info() {
* 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 InfoSection values specifying which sections of information to
* @param options A list of InfoSection values specifying which sections of information to

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param options A list of InfoSection values specifying which sections of information to
* @param options A list of {@link InfoSection} values specifying which sections of information to

* retrieve. When no parameter is provided, the default option is assumed.
* @return CompletableFuture with the response

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @return CompletableFuture with the response
* @return A server response

*/
Expand All @@ -151,7 +153,7 @@ public CompletableFuture<Map> info(InfoOptions options) {
* Get the value associated with the given key, or null if no such value exists.
*
* @see <a href="https://redis.io/commands/get/">redis.io</a> for details.
* @param key - The key to retrieve from the database.
* @param key The key to retrieve from the database.
* @return If `key` exists, returns the value of `key` as a string. Otherwise, return null
*/
@Override
Expand All @@ -168,9 +170,9 @@ public CompletableFuture<String> get(String key) {
* Set the given key with the given value.
*
* @see <a href="https://redis.io/commands/set/">redis.io</a> for details.
* @param key - The key to store.
* @param value - The value to store with the given key.
* @return null
* @param key The key to store.
* @param value The value to store with the given key.
* @return An empty response on success
*/
@Override
public CompletableFuture<Void> set(String key, String value) {
Expand All @@ -186,10 +188,10 @@ public CompletableFuture<Void> set(String key, String value) {
* Set the given key with the given value. Return value is dependent on the passed options.
*
* @see <a href="https://redis.io/commands/set/">redis.io</a> for details.
* @param key - The key to store.
* @param value - The value to store with the given key.
* @param options - The Set options
* @return string or null If value isn't set because of `onlyIfExists` or `onlyIfDoesNotExist`
* @param key The key to store.
* @param value The value to store with the given key.
* @param options The Set options
* @return String or null If value isn't set because of `onlyIfExists` or `onlyIfDoesNotExist`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: taking this from the python client docs:

Suggested change
* @return String or null If value isn't set because of `onlyIfExists` or `onlyIfDoesNotExist`
* @return The old value as a string if `returnOldValue` is set. Otherwise, if the value isn't set because of `onlyIfExists` or `onlyIfDoesNotExist`, return null. Otherwise, return "OK".

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use {@link returnOldValue} (add proper link) instead of just `returnOldValue`

* conditions, return null. If `returnOldValue` is set, return the old value as a string.
*/
@Override
Expand All @@ -201,4 +203,144 @@ public CompletableFuture<String> set(String key, String value, SetOptions option
.build();
return commandManager.submitNewCommand(command, BaseClient::handleStringResponse);
}

/**
* Decrements the number stored at `key` by one. If `key` does not exist, it is set to 0 before

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Decrements the number stored at `key` by one. If `key` does not exist, it is set to 0 before
* Decrements the number stored at <em>key</em> by one. If <em>key</em> does not exist, it is set to 0 before

please repeat this for all functions

* performing the operation.
*
* @see <a href="https://redis.io/commands/decr/">redis.io</a> for details.
* @param key The key to decrement its value.
* @return The value of `key` after the decrement. An error is raised if `key` contains a value of
* the wrong type or contains a string that can not be represented as a long.
*/
@Override
public CompletableFuture<Long> decr(String key) {
Command command =
Command.builder()
.requestType(Command.RequestType.DECR)
.arguments(new String[] {key})
.build();
return commandManager.submitNewCommand(command, BaseClient::handleLongResponse);
}

/**
* Decrements the number stored at `key` by `amount`. If `key` does not exist, it is set to 0
* before performing the operation.
*
* @see <a href="https://redis.io/commands/decrby/">redis.io</a> for details.
* @param key The key to decrement its value.
* @param amount The amount to decrement.
* @return The value of `key` after the decrement. An error is raised if `key` contains a value of
* the wrong type or contains a string that can not be represented as long.
*/
@Override
public CompletableFuture<Long> decrBy(String key, long amount) {
Command command =
Command.builder()
.requestType(Command.RequestType.DECR_BY)
.arguments(new String[] {key, Long.toString(amount)})
.build();
return commandManager.submitNewCommand(command, BaseClient::handleLongResponse);
}

/**
* Increments the number stored at `key` by one. If `key` does not exist, it is set to 0 before
* performing the operation.
*
* @see <a href="https://redis.io/commands/incr/">redis.io</a> for details.
* @param key The key to increment its value.
* @return The value of `key` after the increment, An error is raised if `key` contains a value of

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this should be a period instead of comma, same thing applies for other occurrences in this PR

Suggested change
* @return The value of `key` after the increment, An error is raised if `key` contains a value of
* @return The value of `key` after the increment. An error is raised if `key` contains a value of

* the wrong type or contains a string that can not be represented as long.
*/
@Override
public CompletableFuture<Long> incr(String key) {
Command command =
Command.builder()
.requestType(Command.RequestType.INCR)
.arguments(new String[] {key})
.build();
return commandManager.submitNewCommand(command, BaseClient::handleLongResponse);
}

/**
* Increments the number stored at `key` by `amount`. If `key` does not exist, it is set to 0
* before performing the operation.
*
* @see <a href="https://redis.io/commands/incrby/">redis.io</a> for details.
* @param key The key to increment its value.
* @param amount The amount to increment.
* @return The value of `key` after the increment, An error is raised if `key` contains a value of
* the wrong type or contains a string that can not be represented as long.
*/
@Override
public CompletableFuture<Long> incrBy(String key, long amount) {
Command command =
Command.builder()
.requestType(Command.RequestType.INCR_BY)
.arguments(new String[] {key, Long.toString(amount)})
.build();
return commandManager.submitNewCommand(command, BaseClient::handleLongResponse);
}

/**
* Increment the string representing a floating point number stored at `key` by `amount`. By using
* a negative increment value, the result is that the value stored at `key` is decremented. If
* `key` does not exist, it is set to 0 before performing the operation.
*
* @see <a href="https://redis.io/commands/incrbyfloat/">redis.io</a> for details.
* @param key The key to increment its value.
* @param amount The amount to increment.
* @return The value of `key` after the increment. An error is raised if `key` contains a value of
* the wrong type, or the current key content is not parsable as a double precision floating
* point number.
*/
@Override
public CompletableFuture<Double> incrByFloat(String key, double amount) {
Command command =
Command.builder()
.requestType(Command.RequestType.INCR_BY_FLOAT)
.arguments(new String[] {key, Double.toString(amount)})
.build();
return commandManager.submitNewCommand(command, BaseClient::handleDoubleResponse);
}

/**
* Retrieve the values of multiple keys.
*
* @see <a href="https://redis.io/commands/mget/">redis.io</a> for details.
* @param keys An array of keys to retrieve values for.
* @return An array of values corresponding to the provided keys. If a key is not found, its
* corresponding value in the array will be null.
*/
@Override
public CompletableFuture<String[]> mget(String[] keys) {
Command command =
Command.builder().requestType(Command.RequestType.MGET).arguments(keys).build();
return commandManager
.submitNewCommand(command, BaseClient::handleObjectArrayResponse)
.thenApply(objects -> (String[]) objects);
}

/**
* Set multiple keys to multiple values in a single operation.
*
* @see <a href="https://redis.io/commands/mset/">redis.io</a> for details.
* @param keyValueMap A key-value map consisting of keys and their respective values to set.
* @return An empty response on success
*/
@Override
public CompletableFuture<Void> mset(HashMap<String, String> keyValueMap) {
List<String> flatMap = new ArrayList<>();

for (Map.Entry<String, String> entry : keyValueMap.entrySet()) {
flatMap.add(entry.getKey());
flatMap.add(entry.getValue());
}

String[] args = flatMap.toArray(new String[0]);
Comment on lines +333 to +340

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can avoid creating intermediate list for better performance


Command command =
Command.builder().requestType(Command.RequestType.MSET).arguments(args).build();
return commandManager.submitNewCommand(command, BaseClient::handleVoidResponse);
}
}
21 changes: 20 additions & 1 deletion java/client/src/main/java/glide/api/commands/StringCommands.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
package glide.api.commands;

import glide.api.models.commands.SetOptions;
import java.util.HashMap;
import java.util.concurrent.CompletableFuture;

/** String Commands interface to handle single commands that return Strings. */
/**
* Commands that perform string manipulation.
*
* @see: <a href="https://redis.io/commands/?group=string">String Commands</a>
*/
public interface StringCommands {

CompletableFuture<String> get(String key);

CompletableFuture<Void> set(String key, String value);

CompletableFuture<String> set(String key, String value, SetOptions options);

CompletableFuture<Long> decr(String key);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move all javadocs from client to here - for all functions.


CompletableFuture<Long> decrBy(String key, long amount);

CompletableFuture<Long> incr(String key);

CompletableFuture<Long> incrBy(String key, long amount);

CompletableFuture<Double> incrByFloat(String key, double amount);

CompletableFuture<String[]> mget(String[] keys);

CompletableFuture<Void> mset(HashMap<String, String> keyValueMap);
}
14 changes: 14 additions & 0 deletions java/client/src/main/java/glide/managers/CommandManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ private RequestType mapRequestTypes(Command.RequestType inType) {
return RequestType.GetString;
case SET_STRING:
return RequestType.SetString;
case DECR:
return RequestType.Decr;
case DECR_BY:
return RequestType.DecrBy;
case INCR:
return RequestType.Incr;
case INCR_BY:
return RequestType.IncrBy;
case INCR_BY_FLOAT:
return RequestType.IncrByFloat;
case MGET:
return RequestType.MGet;
case MSET:
return RequestType.MSet;
}
throw new RuntimeException("Unsupported request type");
}
Expand Down
Loading
Loading