-
Notifications
You must be signed in to change notification settings - Fork 68
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 custom command interface; and BaseCommands #798
Closed
acarbonetto
wants to merge
3
commits into
valkey-io:main
from
Bit-Quill:java/integ_acarbo_api_baseCommands
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
java/client/src/main/java/glide/api/commands/BaseCommandResponseResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package glide.api.commands; | ||
|
||
import glide.api.models.exceptions.ClosingException; | ||
import glide.api.models.exceptions.ConnectionException; | ||
import glide.api.models.exceptions.ExecAbortException; | ||
import glide.api.models.exceptions.RedisException; | ||
import glide.api.models.exceptions.RequestException; | ||
import glide.api.models.exceptions.TimeoutException; | ||
import lombok.AllArgsConstructor; | ||
import response.ResponseOuterClass.RequestError; | ||
import response.ResponseOuterClass.Response; | ||
|
||
/** | ||
* Response resolver responsible for evaluating the Redis response object with a success or failure. | ||
*/ | ||
@AllArgsConstructor | ||
public class BaseCommandResponseResolver | ||
implements RedisExceptionCheckedFunction<Response, Object> { | ||
|
||
private RedisExceptionCheckedFunction<Long, Object> respPointerResolver; | ||
|
||
/** | ||
* Extracts value from the RESP pointer. <br> | ||
* Throws errors when the response is unsuccessful. | ||
* | ||
* @return A generic Object with the Response | null if the response is empty | ||
*/ | ||
public Object apply(Response response) throws RedisException { | ||
// TODO: handle object if the object is small | ||
// TODO: handle RESP2 object if configuration is set | ||
if (response.hasRequestError()) { | ||
RequestError error = response.getRequestError(); | ||
String msg = error.getMessage(); | ||
switch (error.getType()) { | ||
case Unspecified: | ||
// Unspecified error on Redis service-side | ||
throw new RequestException(msg); | ||
case ExecAbort: | ||
// Transactional error on Redis service-side | ||
throw new ExecAbortException(msg); | ||
case Timeout: | ||
// Timeout from Glide to Redis service | ||
throw new TimeoutException(msg); | ||
case Disconnect: | ||
// Connection problem between Glide and Redis | ||
throw new ConnectionException(msg); | ||
default: | ||
// Request or command error from Redis | ||
throw new RequestException(msg); | ||
} | ||
} | ||
if (response.hasClosingError()) { | ||
// A closing error is thrown when Rust-core is not connected to Redis | ||
// We want to close shop and throw a ClosingException | ||
// TODO: close the channel on a closing error | ||
// channel.close(); | ||
throw new ClosingException(response.getClosingError()); | ||
} | ||
if (response.hasConstantResponse()) { | ||
// Return "OK" | ||
return response.getConstantResponse().toString(); | ||
} | ||
if (response.hasRespPointer()) { | ||
// Return the shared value - which may be a null value | ||
return respPointerResolver.apply(response.getRespPointer()); | ||
} | ||
// if no response payload is provided, assume null | ||
return null; | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
java/client/src/main/java/glide/api/commands/BaseCommands.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package glide.api.commands; | ||
|
||
import glide.ffi.resolvers.RedisValueResolver; | ||
import java.util.List; | ||
import java.util.concurrent.CompletableFuture; | ||
import response.ResponseOuterClass.Response; | ||
|
||
/** Base Commands interface to handle generic command and transaction requests. */ | ||
public interface BaseCommands { | ||
|
||
/** | ||
* default Object handler from response | ||
* | ||
* @return BaseCommandResponseResolver to deliver the response | ||
*/ | ||
static BaseCommandResponseResolver applyBaseCommandResponseResolver() { | ||
return new BaseCommandResponseResolver(RedisValueResolver::valueFromPointer); | ||
} | ||
|
||
/** | ||
* Extracts the response from the Protobuf response and either throws an exception or returns the | ||
* appropriate response has an Object | ||
* | ||
* @param response Redis protobuf message | ||
* @return Response Object | ||
*/ | ||
static Object handleObjectResponse(Response response) { | ||
// return function to convert protobuf.Response into the response object by | ||
// calling valueFromPointer | ||
return BaseCommands.applyBaseCommandResponseResolver().apply(response); | ||
} | ||
|
||
public static List<Object> handleTransactionResponse(Response response) { | ||
// return function to convert protobuf.Response into the response object by | ||
// calling valueFromPointer | ||
|
||
List<Object> transactionResponse = | ||
(List<Object>) BaseCommands.applyBaseCommandResponseResolver().apply(response); | ||
return transactionResponse; | ||
} | ||
|
||
/** | ||
* Execute a @see{Command} by sending command via socket manager | ||
* | ||
* @param args arguments for the custom command | ||
* @return a CompletableFuture with response result from Redis | ||
*/ | ||
CompletableFuture<Object> customCommand(String[] args); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package glide.api.commands; | ||
|
||
import lombok.Builder; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.Getter; | ||
import lombok.NonNull; | ||
|
||
/** Base Command class to send a single request to Redis. */ | ||
@Builder | ||
@Getter | ||
@EqualsAndHashCode | ||
public class Command { | ||
|
||
/** Redis command request type */ | ||
@NonNull final RequestType requestType; | ||
|
||
/** List of Arguments for the Redis command request */ | ||
@Builder.Default final String[] arguments = new String[] {}; | ||
|
||
public enum RequestType { | ||
/** Call a custom command with list of string arguments */ | ||
CUSTOM_COMMAND, | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
java/client/src/main/java/glide/api/commands/RedisExceptionCheckedFunction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package glide.api.commands; | ||
|
||
import glide.api.models.exceptions.RedisException; | ||
|
||
@FunctionalInterface | ||
public interface RedisExceptionCheckedFunction<R, T> { | ||
|
||
/** | ||
* Functional response handler that takes a protobuf Response object. <br> | ||
* Returns a typed object on a successful Redis response. <br> | ||
* Throws RedisException when receiving a Redis error response. <br> | ||
* | ||
* @param response - Redis Response | ||
* @return T - response payload type | ||
* @throws RedisException | ||
*/ | ||
T apply(R response) throws RedisException; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the interface is public to the use, this will also be public to the user. Why do we want to expose this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. I can hide this from the user, like
RedisValueResolver::valueFromPointer
is not being exposed.This also applies to
BaseCommandResponseResolver
class?