1
1
package glide .managers ;
2
2
3
- import glide .api .models .exceptions .ClosingException ;
4
- import glide .api .models .exceptions .ConnectionException ;
5
- import glide .api .models .exceptions .ExecAbortException ;
6
- import glide .api .models .exceptions .RedisException ;
7
- import glide .api .models .exceptions .RequestException ;
8
- import glide .api .models .exceptions .TimeoutException ;
9
3
import glide .connectors .handlers .ChannelHandler ;
10
- import glide .ffi .resolvers .RedisValueResolver ;
11
- import glide .models .RequestBuilder ;
12
- import java .util .List ;
4
+ import glide .managers .models .Command ;
13
5
import java .util .concurrent .CompletableFuture ;
14
6
import lombok .RequiredArgsConstructor ;
7
+ import redis_request .RedisRequestOuterClass ;
15
8
import redis_request .RedisRequestOuterClass .RequestType ;
16
- import response .ResponseOuterClass .RequestError ;
17
9
import response .ResponseOuterClass .Response ;
18
10
19
11
/**
@@ -27,82 +19,56 @@ public class CommandManager {
27
19
private final ChannelHandler channel ;
28
20
29
21
/**
30
- * Async (non-blocking) get.<br>
31
- * See <a href="https://redis.io/commands/get/">REDIS docs for GET</a>.
22
+ * Build a command and send.
32
23
*
33
- * @param key The key name
24
+ * @param command
25
+ * @param responseHandler - to handle the response object
26
+ * @return A result promise of type T
34
27
*/
35
- public CompletableFuture <String > get (String key ) {
36
- return submitNewRequest (RequestType .GetString , List .of (key ));
28
+ public <T > CompletableFuture <T > submitNewCommand (
29
+ Command command , RedisExceptionCheckedFunction <Response , T > responseHandler ) {
30
+ // write command request to channel
31
+ // when complete, convert the response to our expected type T using the given responseHandler
32
+ return channel
33
+ .write (prepareRedisRequest (command .getRequestType (), command .getArguments ()), true )
34
+ .thenApplyAsync (response -> responseHandler .apply (response ));
37
35
}
38
36
39
37
/**
40
- * Async (non-blocking) set .<br>
41
- * See <a href="https://redis.io/commands/set/">REDIS docs for SET</a> .
38
+ * Build a protobuf command/transaction request object .<br>
39
+ * Used by {@link CommandManager} .
42
40
*
43
- * @param key The key name
44
- * @param value The value to set
41
+ * @param command - Redis command
42
+ * @param args - Redis command arguments as string array
43
+ * @return An uncompleted request. CallbackDispatcher is responsible to complete it by adding a
44
+ * callback id.
45
45
*/
46
- public CompletableFuture <String > set (String key , String value ) {
47
- return submitNewRequest (RequestType .SetString , List .of (key , value ));
48
- }
46
+ private RedisRequestOuterClass .RedisRequest .Builder prepareRedisRequest (
47
+ Command .RequestType command , String [] args ) {
48
+ RedisRequestOuterClass .Command .ArgsArray .Builder commandArgs =
49
+ RedisRequestOuterClass .Command .ArgsArray .newBuilder ();
50
+ for (var arg : args ) {
51
+ commandArgs .addArgs (arg );
52
+ }
49
53
50
- /**
51
- * Build a command and submit it Netty to send.
52
- *
53
- * @param command Command type
54
- * @param args Command arguments
55
- * @return A result promise
56
- */
57
- private CompletableFuture < String > submitNewRequest ( RequestType command , List < String > args ) {
58
- return channel
59
- . write ( RequestBuilder . prepareRedisRequest ( command , args ), true )
60
- . thenApplyAsync ( this :: extractValueFromGlideRsResponse );
54
+ // TODO: set route properly when no RouteOptions given
55
+ return RedisRequestOuterClass . RedisRequest . newBuilder ()
56
+ . setSingleCommand (
57
+ RedisRequestOuterClass . Command . newBuilder ()
58
+ . setRequestType ( mapRequestTypes ( command ))
59
+ . setArgsArray ( commandArgs . build ())
60
+ . build ())
61
+ . setRoute (
62
+ RedisRequestOuterClass . Routes . newBuilder ()
63
+ . setSimpleRoutes ( RedisRequestOuterClass . SimpleRoutes . AllNodes )
64
+ . build () );
61
65
}
62
66
63
- /**
64
- * Check response and extract data from it.
65
- *
66
- * @param response A response received from rust core lib
67
- * @return A String from the Redis response, or Ok. Otherwise, returns null
68
- */
69
- private String extractValueFromGlideRsResponse (Response response ) {
70
- if (response .hasRequestError ()) {
71
- RequestError error = response .getRequestError ();
72
- String msg = error .getMessage ();
73
- switch (error .getType ()) {
74
- case Unspecified :
75
- // Unspecified error on Redis service-side
76
- throw new RequestException (msg );
77
- case ExecAbort :
78
- // Transactional error on Redis service-side
79
- throw new ExecAbortException (msg );
80
- case Timeout :
81
- // Timeout from Glide to Redis service
82
- throw new TimeoutException (msg );
83
- case Disconnect :
84
- // Connection problem between Glide and Redis
85
- throw new ConnectionException (msg );
86
- default :
87
- // Request or command error from Redis
88
- throw new RedisException (msg );
89
- }
90
- }
91
- if (response .hasClosingError ()) {
92
- // A closing error is thrown when Rust-core is not connected to Redis
93
- // We want to close shop and throw a ClosingException
94
- channel .close ();
95
- throw new ClosingException (response .getClosingError ());
96
- }
97
- if (response .hasConstantResponse ()) {
98
- // Return "OK"
99
- return response .getConstantResponse ().toString ();
100
- }
101
- if (response .hasRespPointer ()) {
102
- // Return the shared value - which may be a null value
103
- return RedisValueResolver .valueFromPointer (response .getRespPointer ()).toString ();
67
+ private RequestType mapRequestTypes (Command .RequestType inType ) {
68
+ switch (inType ) {
69
+ case CUSTOM_COMMAND :
70
+ return RequestType .CustomCommand ;
104
71
}
105
- // if no response payload is provided, assume null
106
- return null ;
72
+ throw new RuntimeException ("Unsupported request type" );
107
73
}
108
74
}
0 commit comments