forked from valkey-io/valkey-glide
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Open channel (connection) per client, share thread pools.
Signed-off-by: Yury-Fridlyand <[email protected]>
- Loading branch information
1 parent
fbff211
commit 701da44
Showing
9 changed files
with
143 additions
and
118 deletions.
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
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,32 @@ | ||
package babushka; | ||
|
||
import babushka.client.ChannelHolder; | ||
import babushka.client.Commands; | ||
import babushka.client.Connection; | ||
import babushka.connection.CallbackManager; | ||
import babushka.connection.SocketManager; | ||
import java.nio.channels.NotYetConnectedException; | ||
import lombok.Getter; | ||
|
||
public class Client { | ||
|
||
private final ChannelHolder channelHolder; | ||
private final Commands commands; | ||
@Getter private final Connection connection; | ||
|
||
public Client() { | ||
var callBackManager = new CallbackManager(); | ||
channelHolder = | ||
new ChannelHolder( | ||
SocketManager.getInstance().openNewChannel(callBackManager), callBackManager); | ||
connection = new Connection(channelHolder); | ||
commands = new Commands(channelHolder); | ||
} | ||
|
||
public Commands getCommands() { | ||
if (!connection.isConnected()) { | ||
throw new NotYetConnectedException(); | ||
} | ||
return commands; | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
java/client/src/main/java/babushka/client/ChannelHolder.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,40 @@ | ||
package babushka.client; | ||
|
||
import babushka.connection.CallbackManager; | ||
import connection_request.ConnectionRequestOuterClass.ConnectionRequest; | ||
import io.netty.channel.Channel; | ||
import java.util.concurrent.CompletableFuture; | ||
import lombok.RequiredArgsConstructor; | ||
import redis_request.RedisRequestOuterClass.RedisRequest; | ||
import response.ResponseOuterClass.Response; | ||
|
||
@RequiredArgsConstructor | ||
public class ChannelHolder { | ||
private final Channel channel; | ||
private final CallbackManager callbackManager; | ||
|
||
/** Write a protobuf message to the socket. */ | ||
public CompletableFuture<Response> write(RedisRequest.Builder request, boolean flush) { | ||
var commandId = callbackManager.registerRequest(); | ||
request.setCallbackIdx(commandId.getKey()); | ||
|
||
if (flush) { | ||
channel.writeAndFlush(request.build().toByteArray()); | ||
} else { | ||
channel.write(request.build().toByteArray()); | ||
} | ||
return commandId.getValue(); | ||
} | ||
|
||
/** Write a protobuf message to the socket. */ | ||
public CompletableFuture<Response> connect(ConnectionRequest request) { | ||
channel.writeAndFlush(request.toByteArray()); | ||
return callbackManager.getConnectionPromise(); | ||
} | ||
|
||
/** Closes the UDS connection and frees corresponding resources. */ | ||
public void close() { | ||
channel.close(); | ||
callbackManager.clean(); | ||
} | ||
} |
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
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
43 changes: 12 additions & 31 deletions
43
java/client/src/main/java/babushka/connection/CallbackManager.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 |
---|---|---|
@@ -1,81 +1,62 @@ | ||
package babushka.connection; | ||
|
||
import java.util.Deque; | ||
import java.util.Map; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.ConcurrentLinkedDeque; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
import lombok.Getter; | ||
import org.apache.commons.lang3.tuple.Pair; | ||
import response.ResponseOuterClass.Response; | ||
|
||
/** Holder for resources owned by {@link SocketManager} and used by {@link ReadHandler}. */ | ||
class CallbackManager { | ||
public class CallbackManager { | ||
|
||
/** Unique request ID (callback ID). Thread-safe. */ | ||
private static final AtomicInteger requestId = new AtomicInteger(0); | ||
private final AtomicInteger requestId = new AtomicInteger(0); | ||
|
||
/** | ||
* Storage of Futures to handle responses. Map key is callback id, which starts from 1.<br> | ||
* Each future is a promise for every submitted by user request. | ||
*/ | ||
private static final Map<Integer, CompletableFuture<Response>> responses = | ||
new ConcurrentHashMap<>(); | ||
private final Map<Integer, CompletableFuture<Response>> responses = new ConcurrentHashMap<>(); | ||
|
||
/** | ||
* Storage for connection requests similar to {@link #responses}. Unfortunately, connection | ||
* Storage for connection request similar to {@link #responses}. Unfortunately, connection | ||
* requests can't be stored in the same storage, because callback ID = 0 is hardcoded for | ||
* connection requests. Will be removed once <a | ||
* href="https://github.com/aws/babushka/issues/600">issue #600 on GH</a> fixed. | ||
* connection requests. | ||
*/ | ||
private static final Deque<CompletableFuture<Response>> connectionRequests = | ||
new ConcurrentLinkedDeque<>(); | ||
@Getter private final CompletableFuture<Response> connectionPromise = new CompletableFuture<>(); | ||
|
||
/** | ||
* Register a new request to be sent. Once response received, the given future completes with it. | ||
* | ||
* @return A pair of unique callback ID which should set into request and a client promise for | ||
* response. | ||
*/ | ||
public static Pair<Integer, CompletableFuture<Response>> registerRequest() { | ||
public Pair<Integer, CompletableFuture<Response>> registerRequest() { | ||
int callbackId = requestId.incrementAndGet(); | ||
var future = new CompletableFuture<Response>(); | ||
responses.put(callbackId, future); | ||
return Pair.of(callbackId, future); | ||
} | ||
|
||
/** | ||
* Register a new connection request similar to {@link #registerRequest}.<br> | ||
* No callback ID returned, because connection request/response pair have no such field (subject | ||
* to change). Track <a href="https://github.com/aws/babushka/issues/600">issue #600</a> for more | ||
* details. | ||
*/ | ||
public static CompletableFuture<Response> registerConnection() { | ||
var future = new CompletableFuture<Response>(); | ||
connectionRequests.add(future); | ||
return future; | ||
} | ||
|
||
/** | ||
* Complete the corresponding client promise and free resources. | ||
* | ||
* @param response A response received | ||
*/ | ||
public static void completeRequest(Response response) { | ||
public void completeRequest(Response response) { | ||
int callbackId = response.getCallbackIdx(); | ||
if (callbackId == 0) { | ||
// can't distinguish connection requests since they have no | ||
// callback ID | ||
// https://github.com/aws/babushka/issues/600 | ||
connectionRequests.pop().completeAsync(() -> response); | ||
connectionPromise.completeAsync(() -> response); | ||
} else { | ||
responses.get(callbackId).completeAsync(() -> response); | ||
responses.remove(callbackId); | ||
} | ||
} | ||
|
||
public static void clean() { | ||
public void clean() { | ||
// TODO should we reply in uncompleted futures? | ||
connectionRequests.clear(); | ||
responses.clear(); | ||
} | ||
} |
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
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.