use of org.apache.ratis.protocol.exceptions.ResourceUnavailableException in project incubator-ratis by apache.
the class RaftClientImpl method handleIOException.
void handleIOException(RaftClientRequest request, IOException ioe, RaftPeerId newLeader, Consumer<RaftClientRequest> handler) {
LOG.debug("{}: suggested new leader: {}. Failed {} with {}", clientId, newLeader, request, ioe);
if (LOG.isTraceEnabled()) {
LOG.trace("Stack trace", new Throwable("TRACE"));
}
Optional.ofNullable(handler).ifPresent(h -> h.accept(request));
if (ioe instanceof LeaderNotReadyException || ioe instanceof ResourceUnavailableException) {
return;
}
final RaftPeerId oldLeader = request.getServerId();
final RaftPeerId curLeader = leaderId;
final boolean stillLeader = oldLeader.equals(curLeader);
if (newLeader == null && stillLeader) {
newLeader = CollectionUtils.random(oldLeader, CollectionUtils.as(peers, RaftPeer::getId));
}
LOG.debug("{}: oldLeader={}, curLeader={}, newLeader={}", clientId, oldLeader, curLeader, newLeader);
final boolean changeLeader = newLeader != null && stillLeader;
final boolean reconnect = changeLeader || clientRpc.shouldReconnect(ioe);
if (reconnect) {
if (changeLeader && oldLeader.equals(leaderId)) {
LOG.debug("{} {}: client change Leader from {} to {} ex={}", groupId, clientId, oldLeader, newLeader, ioe.getClass().getName());
this.leaderId = newLeader;
}
clientRpc.handleException(oldLeader, ioe, true);
}
}
use of org.apache.ratis.protocol.exceptions.ResourceUnavailableException in project incubator-ratis by apache.
the class RaftServerImpl method appendTransaction.
/**
* Handle a normal update request from client.
*/
private CompletableFuture<RaftClientReply> appendTransaction(RaftClientRequest request, TransactionContext context, CacheEntry cacheEntry) throws IOException {
assertLifeCycleState(LifeCycle.States.RUNNING);
CompletableFuture<RaftClientReply> reply;
final PendingRequest pending;
synchronized (this) {
reply = checkLeaderState(request, cacheEntry, true);
if (reply != null) {
return reply;
}
// append the message to its local log
final LeaderStateImpl leaderState = role.getLeaderStateNonNull();
final PendingRequests.Permit permit = leaderState.tryAcquirePendingRequest(request.getMessage());
if (permit == null) {
cacheEntry.failWithException(new ResourceUnavailableException(getMemberId() + ": Failed to acquire a pending write request for " + request));
return cacheEntry.getReplyFuture();
}
try {
state.appendLog(context);
} catch (StateMachineException e) {
// the StateMachineException is thrown by the SM in the preAppend stage.
// Return the exception in a RaftClientReply.
RaftClientReply exceptionReply = newExceptionReply(request, e);
cacheEntry.failWithReply(exceptionReply);
// leader will step down here
if (e.leaderShouldStepDown() && getInfo().isLeader()) {
leaderState.submitStepDownEvent(LeaderState.StepDownReason.STATE_MACHINE_EXCEPTION);
}
return CompletableFuture.completedFuture(exceptionReply);
}
// put the request into the pending queue
pending = leaderState.addPendingRequest(permit, request, context);
if (pending == null) {
cacheEntry.failWithException(new ResourceUnavailableException(getMemberId() + ": Failed to add a pending write request for " + request));
return cacheEntry.getReplyFuture();
}
leaderState.notifySenders();
}
return pending.getFuture();
}
use of org.apache.ratis.protocol.exceptions.ResourceUnavailableException in project incubator-ratis by apache.
the class TestRetryCacheWithGrpc method testRetryOnResourceUnavailableException.
@Test(timeout = 10000)
public void testRetryOnResourceUnavailableException() throws InterruptedException, IOException {
RaftProperties properties = new RaftProperties();
properties.setClass(MiniRaftCluster.STATEMACHINE_CLASS_KEY, SimpleStateMachine4Testing.class, StateMachine.class);
RaftServerConfigKeys.Write.setElementLimit(properties, 1);
MiniRaftClusterWithGrpc cluster = getFactory().newCluster(NUM_SERVERS, properties);
cluster.start();
final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
final RaftServer leaderProxy = leader.getRaftServer();
for (RaftServer.Division follower : cluster.getFollowers()) {
// block followers to trigger ResourceUnavailableException
((SimpleStateMachine4Testing) follower.getStateMachine()).blockWriteStateMachineData();
}
AtomicBoolean failure = new AtomicBoolean(false);
long callId = 1;
ClientId clientId = ClientId.randomId();
RaftClientRequest r = null;
while (!failure.get()) {
long cid = callId;
r = cluster.newRaftClientRequest(clientId, leaderProxy.getId(), callId++, new RaftTestUtil.SimpleMessage("message"));
CompletableFuture<RaftClientReply> f = leaderProxy.submitClientRequestAsync(r);
f.exceptionally(e -> {
if (e.getCause() instanceof ResourceUnavailableException) {
RetryCacheTestUtil.isFailed(RetryCacheTestUtil.get(leader, clientId, cid));
failure.set(true);
}
return null;
});
}
for (RaftServer.Division follower : cluster.getFollowers()) {
// unblock followers
((SimpleStateMachine4Testing) follower.getStateMachine()).unblockWriteStateMachineData();
}
while (failure.get()) {
try {
// retry until the request failed with ResourceUnavailableException succeeds.
RaftClientReply reply = leaderProxy.submitClientRequestAsync(r).get();
if (reply.isSuccess()) {
failure.set(false);
}
} catch (Exception e) {
// Ignore the exception
}
}
cluster.shutdown();
}
Aggregations