-
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 RedisException return to connection/command response handl… #788
Changes from 1 commit
2ef4f38
37fee4a
e8da8e5
fbddc6f
0ad55d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package glide.api.models.exceptions; | ||
|
||
/** Error returned from Redis client: Redis is closing or unavailable to the client */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't invent new documentation, just use the existing comments used in python / TS. Same for all exception types. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed under 37fee4a |
||
public class ClosingException extends RedisException { | ||
public ClosingException(String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package glide.api.models.exceptions; | ||
|
||
/** | ||
* Error returned from Redis client: Redis connection is disconnected or unavailable to the client | ||
*/ | ||
public class ConnectionException extends RedisException { | ||
public ConnectionException(String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package glide.api.models.exceptions; | ||
|
||
/** Error returned from Redis client: due to transaction execution abort */ | ||
public class ExecAbortException extends RedisException { | ||
public ExecAbortException(String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package glide.api.models.exceptions; | ||
|
||
/** Encapsulated an error returned from the Redis or during processing of a Redis request */ | ||
public class RedisException extends RuntimeException { | ||
public RedisException(String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package glide.api.models.exceptions; | ||
|
||
/** Error returned from Redis client: Redis request has failed */ | ||
public class RequestException extends RedisException { | ||
public RequestException(String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package glide.api.models.exceptions; | ||
|
||
/** Error returned from Redis client: request has timed out */ | ||
public class TimeoutException extends RedisException { | ||
public TimeoutException(String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,9 +12,13 @@ | |
import glide.api.models.configuration.ReadFrom; | ||
import glide.api.models.configuration.RedisClientConfiguration; | ||
import glide.api.models.configuration.RedisClusterClientConfiguration; | ||
import glide.api.models.exceptions.ClosingException; | ||
import glide.connectors.handlers.ChannelHandler; | ||
import io.netty.channel.ChannelFuture; | ||
import io.netty.util.concurrent.GenericFutureListener; | ||
import java.util.concurrent.CompletableFuture; | ||
import lombok.RequiredArgsConstructor; | ||
import response.ResponseOuterClass.RequestError; | ||
import response.ResponseOuterClass.Response; | ||
|
||
/** | ||
|
@@ -162,28 +166,51 @@ private ConnectionRequestOuterClass.ReadFrom mapReadFromEnum(ReadFrom readFrom) | |
/** Check a response received from Glide. */ | ||
private Void checkGlideRsResponse(Response response) { | ||
if (response.hasRequestError()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor: closeConnection();
throw new ClosingException(<some message>); maybe just invert the structure of the function: private Void checkGlideRsResponse(Response response) {
if (response.hasConstantResponse()) {
return null;
}
var message;
[...] // set message by the response type
closeConnection();
throw new ClosingException(message);
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't trust that there is no error in the response. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consolidated the logic in 37fee4a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Why not? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Best practices. I just don't know how core (and any interactive system) would behave in the future. And this provides an extra layer of protection for the user. I'm not sure the saving in processing time here are worth the potential costs of exposing a bug down the road. |
||
// TODO support different types of exceptions and distinguish them by type: | ||
throw new RuntimeException( | ||
String.format( | ||
"%s: %s", | ||
response.getRequestError().getType(), response.getRequestError().getMessage())); | ||
closeConnection(); | ||
RequestError error = response.getRequestError(); | ||
throw new ClosingException("Unexpected request error in response: " + error.getMessage()); | ||
} | ||
if (response.hasClosingError()) { | ||
throw new RuntimeException("Connection closed: " + response.getClosingError()); | ||
// A closing error is thrown when Rust-core is not connected to Redis | ||
// We want to close shop and throw a ClosingException | ||
closeConnection(); | ||
throw new ClosingException(response.getClosingError()); | ||
} | ||
if (response.hasRespPointer()) { | ||
// TODO: throw ClosingException and close/cancel all existing responses | ||
throw new RuntimeException("Unexpected data in response"); | ||
closeConnection(); | ||
throw new ClosingException("Unexpected data in response"); | ||
} | ||
if (response.hasConstantResponse()) { | ||
// successful connection response has an "OK" | ||
return null; | ||
if (!response.hasConstantResponse()) { | ||
closeConnection(); | ||
throw new ClosingException("Unexpected empty data in response"); | ||
} | ||
throw new RuntimeException("Connection response expects an OK response"); | ||
// successful connection response has an "OK" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the comment doesn't match the return type. what's intention behind the doc? |
||
return null; | ||
} | ||
|
||
/** Close the connection and the corresponding channel. */ | ||
/** Close the connection to the channel. */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment on nothing, repeating the next comment |
||
|
||
/** | ||
* Close the connection to the channel. | ||
* | ||
* @return a CompletableFuture to indicate the channel is closed | ||
*/ | ||
public CompletableFuture<Void> closeConnection() { | ||
return CompletableFuture.runAsync(channel::close); | ||
CompletableFuture<Void> completableFuture = new CompletableFuture<>(); | ||
channel | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can update this function to return |
||
.close() | ||
.syncUninterruptibly() | ||
.addListener( | ||
(GenericFutureListener<ChannelFuture>) | ||
future -> { | ||
if (future.isCancelled()) { | ||
completableFuture.cancel(false); | ||
} else if (future.isDone()) { | ||
completableFuture.complete(null); | ||
} | ||
completableFuture.completeExceptionally( | ||
new RuntimeException("Channel failed to close")); | ||
}); | ||
return completableFuture; | ||
} | ||
} |
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.
I'm sorry I didn't notice earlier - we use 4 spaces throughout the project:
https://github.com/aws/glide-for-redis/blob/2f901b0617fe1cce76de8449f9fc28ba30029c2d/.vscode/settings.json#L3
please fix your linter in a separate PR.