use of org.apache.ratis.protocol.ClientInvocationId in project incubator-ratis by apache.
the class NettyClientStreamRpc method streamAsync.
@Override
public CompletableFuture<DataStreamReply> streamAsync(DataStreamRequest request) {
final CompletableFuture<DataStreamReply> f = new CompletableFuture<>();
ClientInvocationId clientInvocationId = ClientInvocationId.valueOf(request.getClientId(), request.getStreamId());
final ReplyQueue q = replies.computeIfAbsent(clientInvocationId, key -> new ReplyQueue());
if (!q.offer(f)) {
f.completeExceptionally(new IllegalStateException(this + ": Failed to offer a future for " + request));
return f;
}
LOG.debug("{}: write {}", this, request);
getChannel().writeAndFlush(request);
return f;
}
use of org.apache.ratis.protocol.ClientInvocationId in project incubator-ratis by apache.
the class DataStreamManagement method readImpl.
private void readImpl(DataStreamRequestByteBuf request, ChannelHandlerContext ctx, ByteBuf buf, CheckedBiFunction<RaftClientRequest, Set<RaftPeer>, Set<DataStreamOutputRpc>, IOException> getStreams) {
boolean close = WriteOption.containsOption(request.getWriteOptions(), StandardWriteOption.CLOSE);
ClientInvocationId key = ClientInvocationId.valueOf(request.getClientId(), request.getStreamId());
final StreamInfo info;
if (request.getType() == Type.STREAM_HEADER) {
final MemoizedSupplier<StreamInfo> supplier = JavaUtils.memoize(() -> newStreamInfo(buf, getStreams));
info = streams.computeIfAbsent(key, id -> supplier.get());
if (!supplier.isInitialized()) {
streams.remove(key);
throw new IllegalStateException("Failed to create a new stream for " + request + " since a stream already exists Key: " + key + " StreamInfo:" + info);
}
getMetrics().onRequestCreate(RequestType.HEADER);
} else if (close) {
info = Optional.ofNullable(streams.remove(key)).orElseThrow(() -> new IllegalStateException("Failed to remove StreamInfo for " + request));
} else {
info = Optional.ofNullable(streams.get(key)).orElseThrow(() -> {
streams.remove(key);
return new IllegalStateException("Failed to get StreamInfo for " + request);
});
}
final CompletableFuture<Long> localWrite;
final List<CompletableFuture<DataStreamReply>> remoteWrites;
if (request.getType() == Type.STREAM_HEADER) {
localWrite = CompletableFuture.completedFuture(0L);
remoteWrites = Collections.emptyList();
} else if (request.getType() == Type.STREAM_DATA) {
localWrite = info.getLocal().write(buf, request.getWriteOptions(), writeExecutor);
remoteWrites = info.applyToRemotes(out -> out.write(request, requestExecutor));
} else {
throw new IllegalStateException(this + ": Unexpected type " + request.getType() + ", request=" + request);
}
composeAsync(info.getPrevious(), requestExecutor, n -> JavaUtils.allOf(remoteWrites).thenCombineAsync(localWrite, (v, bytesWritten) -> {
if (request.getType() == Type.STREAM_HEADER || (request.getType() == Type.STREAM_DATA && !close)) {
sendReply(remoteWrites, request, bytesWritten, info.getCommitInfos(), ctx);
} else if (close) {
if (info.isPrimary()) {
// after all server close stream, primary server start transaction
startTransaction(info, request, bytesWritten, ctx);
} else {
sendReply(remoteWrites, request, bytesWritten, info.getCommitInfos(), ctx);
}
} else {
throw new IllegalStateException(this + ": Unexpected type " + request.getType() + ", request=" + request);
}
return null;
}, requestExecutor)).whenComplete((v, exception) -> {
try {
if (exception != null) {
streams.remove(key);
replyDataStreamException(server, exception, info.getRequest(), request, ctx);
}
} finally {
buf.release();
}
});
}
use of org.apache.ratis.protocol.ClientInvocationId in project incubator-ratis by apache.
the class RaftBasicTests method testRequestTimeout.
public static void testRequestTimeout(boolean async, MiniRaftCluster cluster, Logger LOG) throws Exception {
waitForLeader(cluster);
final Timestamp startTime = Timestamp.currentTime();
try (final RaftClient client = cluster.createClient()) {
// Get the next callId to be used by the client
final ClientInvocationId invocationId = RaftClientTestUtil.getClientInvocationId(client);
// Create an entry corresponding to the callId and clientId
// in each server's retry cache.
cluster.getServerAliveStream().forEach(raftServer -> RetryCacheTestUtil.getOrCreateEntry(raftServer, invocationId));
// The retry is successful when the retry cache entry for the corresponding callId and clientId expires.
if (async) {
CompletableFuture<RaftClientReply> replyFuture = client.async().send(new SimpleMessage("abc"));
replyFuture.get();
} else {
client.io().send(new SimpleMessage("abc"));
}
// Eventually the request would be accepted by the server
// when the retry cache entry is invalidated.
// The duration for which the client waits should be more than the retryCacheExpiryDuration.
final TimeDuration duration = startTime.elapsedTime();
TimeDuration retryCacheExpiryDuration = RaftServerConfigKeys.RetryCache.expiryTime(cluster.getProperties());
Assert.assertTrue(duration.compareTo(retryCacheExpiryDuration) >= 0);
}
}
use of org.apache.ratis.protocol.ClientInvocationId in project incubator-ratis by apache.
the class MessageStreamRequests method streamEndOfRequestAsync.
CompletableFuture<ByteString> streamEndOfRequestAsync(RaftClientRequest request) {
final MessageStreamRequestTypeProto stream = request.getType().getMessageStream();
Preconditions.assertTrue(stream.getEndOfRequest());
final ClientInvocationId key = ClientInvocationId.valueOf(request.getClientId(), stream.getStreamId());
final PendingStream pending = streams.remove(key);
if (pending == null) {
return JavaUtils.completeExceptionally(new StreamException(name + ": " + key + " not found"));
}
return pending.getBytes(stream.getMessageId(), request.getMessage());
}
use of org.apache.ratis.protocol.ClientInvocationId in project incubator-ratis by apache.
the class MessageStreamRequests method streamAsync.
CompletableFuture<?> streamAsync(RaftClientRequest request) {
final MessageStreamRequestTypeProto stream = request.getType().getMessageStream();
Preconditions.assertTrue(!stream.getEndOfRequest());
final ClientInvocationId key = ClientInvocationId.valueOf(request.getClientId(), stream.getStreamId());
final PendingStream pending = streams.computeIfAbsent(key);
return pending.append(stream.getMessageId(), request.getMessage());
}
Aggregations