use of org.apache.ratis.protocol.RaftClientReply in project incubator-ratis by apache.
the class RaftReconfigurationBaseTest method runTestReconfTwice.
void runTestReconfTwice(CLUSTER cluster) throws Exception {
final RaftPeerId leaderId = RaftTestUtil.waitForLeader(cluster).getId();
try (final RaftClient client = cluster.createClient(leaderId)) {
// submit some msgs before reconf
for (int i = 0; i < STAGING_CATCHUP_GAP * 2; i++) {
RaftClientReply reply = client.io().send(new SimpleMessage("m" + i));
Assert.assertTrue(reply.isSuccess());
}
final AtomicBoolean reconf1 = new AtomicBoolean(false);
final AtomicBoolean reconf2 = new AtomicBoolean(false);
final AtomicReference<RaftPeer[]> finalPeers = new AtomicReference<>(null);
final AtomicReference<RaftPeer[]> deadPeers = new AtomicReference<>(null);
CountDownLatch latch = new CountDownLatch(1);
Thread clientThread = new Thread(() -> {
try {
PeerChanges c1 = cluster.addNewPeers(2, true);
LOG.info("Start changing the configuration: {}", asList(c1.allPeersInNewConf));
RaftClientReply reply = client.admin().setConfiguration(c1.allPeersInNewConf);
reconf1.set(reply.isSuccess());
PeerChanges c2 = cluster.removePeers(2, true, asList(c1.newPeers));
finalPeers.set(c2.allPeersInNewConf);
deadPeers.set(c2.removedPeers);
LOG.info("Start changing the configuration again: {}", asList(c2.allPeersInNewConf));
reply = client.admin().setConfiguration(c2.allPeersInNewConf);
reconf2.set(reply.isSuccess());
latch.countDown();
} catch (Exception ignored) {
LOG.warn("{} is ignored", JavaUtils.getClassSimpleName(ignored.getClass()), ignored);
}
});
clientThread.start();
latch.await();
Assert.assertTrue(reconf1.get());
Assert.assertTrue(reconf2.get());
waitAndCheckNewConf(cluster, finalPeers.get(), 2, null);
final RaftPeerId leader2 = RaftTestUtil.waitForLeader(cluster).getId();
// check configuration manager's internal state
// each reconf will generate two configurations: (old, new) and (new)
cluster.getServerAliveStream().forEach(server -> {
final ConfigurationManager confManager = RaftServerTestUtil.getConfigurationManager(server);
// each reconf will generate two configurations: (old, new) and (new)
// each leader change generates one configuration.
// expectedConf = 1 (init) + 2*2 (two conf changes) + #leader
final int expectedConf = leader2.equals(leaderId) ? 6 : 7;
Assert.assertEquals(server.getId() + ": " + confManager, expectedConf, confManager.numOfConf());
});
}
}
use of org.apache.ratis.protocol.RaftClientReply in project incubator-ratis by apache.
the class RaftAsyncTests method runTestRequestAsyncWithRetryFailure.
void runTestRequestAsyncWithRetryFailure(boolean initialMessages, CLUSTER cluster) throws Exception {
final TimeDuration sleepTime = HUNDRED_MILLIS;
final RetryLimited retryPolicy = RetryPolicies.retryUpToMaximumCountWithFixedSleep(10, sleepTime);
try (final RaftClient client = cluster.createClient(null, retryPolicy)) {
RaftPeerId leader = null;
if (initialMessages) {
// cluster is already started, send a few success messages
leader = RaftTestUtil.waitForLeader(cluster).getId();
final SimpleMessage[] messages = SimpleMessage.create(10, "initial-");
final List<CompletableFuture<RaftClientReply>> replies = new ArrayList<>();
for (int i = 0; i < messages.length; i++) {
replies.add(client.async().send(messages[i]));
}
for (int i = 0; i < messages.length; i++) {
RaftTestUtil.assertSuccessReply(replies.get(i));
}
// kill the only server
cluster.killServer(leader);
}
// now, either the cluster is not yet started or the server is killed.
final List<CompletableFuture<RaftClientReply>> replies = new ArrayList<>();
{
final SimpleMessage[] messages = SimpleMessage.create(10);
int i = 0;
// send half of the calls without starting the cluster
for (; i < messages.length / 2; i++) {
replies.add(client.async().send(messages[i]));
}
// sleep most of the retry time
sleepTime.apply(t -> t * (retryPolicy.getMaxAttempts() - 1)).sleep();
// send another half of the calls without starting the cluster
for (; i < messages.length; i++) {
replies.add(client.async().send(messages[i]));
}
Assert.assertEquals(messages.length, replies.size());
}
// sleep again so that the first half calls will fail retries.
// the second half still have retry time remaining.
sleepTime.apply(t -> t * 2).sleep();
if (leader != null) {
cluster.restartServer(leader, false);
} else {
cluster.start();
}
// all the calls should fail for ordering guarantee
for (int i = 0; i < replies.size(); i++) {
final CheckedRunnable<Exception> getReply = replies.get(i)::get;
final String name = "retry-failure-" + i;
if (i == 0) {
final Throwable t = testFailureCase(name, getReply, ExecutionException.class, RaftRetryFailureException.class);
assertRaftRetryFailureException((RaftRetryFailureException) t.getCause(), retryPolicy, name);
} else {
testFailureCase(name, getReply, ExecutionException.class, AlreadyClosedException.class, RaftRetryFailureException.class);
}
}
testFailureCaseAsync("last-request", () -> client.async().send(new SimpleMessage("last")), AlreadyClosedException.class, RaftRetryFailureException.class);
}
}
use of org.apache.ratis.protocol.RaftClientReply in project incubator-ratis by apache.
the class RaftAsyncTests method runTestNoRetryWaitOnNotLeaderException.
private void runTestNoRetryWaitOnNotLeaderException(MiniRaftCluster cluster) throws Exception {
final RaftServer.Division leader = waitForLeader(cluster);
final List<RaftServer.Division> followers = cluster.getFollowers();
Assert.assertNotNull(followers);
Assert.assertEquals(2, followers.size());
Assert.assertNotSame(leader, followers.get(0));
Assert.assertNotSame(leader, followers.get(1));
// send a message to make sure that the leader is ready
try (final RaftClient client = cluster.createClient(leader.getId())) {
final CompletableFuture<RaftClientReply> f = client.async().send(new SimpleMessage("first"));
FIVE_SECONDS.apply(f::get);
}
// if sleep interval defined by retry policy is used the test will timeout
final RetryPolicy r = event -> () -> TimeDuration.valueOf(60, TimeUnit.SECONDS);
try (final RaftClient client = cluster.createClient(followers.get(0).getId(), cluster.getGroup(), r)) {
final CompletableFuture<RaftClientReply> f = client.async().send(new SimpleMessage("abc"));
FIVE_SECONDS.apply(f::get);
} catch (TimeoutException e) {
throw new AssertionError("Failed to get async result", e);
}
}
use of org.apache.ratis.protocol.RaftClientReply in project incubator-ratis by apache.
the class RequestLimitAsyncBaseTest method runTestWriteElementLimit.
void runTestWriteElementLimit(CLUSTER cluster) throws Exception {
final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
try (RaftClient c1 = cluster.createClient(leader.getId())) {
{
// send first message to make sure the cluster is working
final SimpleMessage message = new SimpleMessage("first");
final CompletableFuture<RaftClientReply> future = c1.async().send(message);
final RaftClientReply reply = getWithDefaultTimeout(future);
Assert.assertTrue(reply.isSuccess());
}
// collecting futures returned from StateMachine.applyTransaction
final BlockingQueue<Runnable> toBeCompleted = SimpleStateMachine4Testing.get(leader).collecting().enable(SimpleStateMachine4Testing.Collecting.Type.APPLY_TRANSACTION);
// send write requests up to the limit
final List<CompletableFuture<RaftClientReply>> writeFutures = new ArrayList<>();
for (int i = 0; i < writeElementLimit; i++) {
final SimpleMessage message = new SimpleMessage("m" + i);
writeFutures.add(c1.async().send(message));
}
// send watch requests up to the limit
// watch a large index so that it won't complete
final long watchBase = 1000;
for (int i = 0; i < watchElementLimit; i++) {
c1.async().watch(watchBase + i, ReplicationLevel.ALL);
}
// sleep to make sure that all the request were sent
HUNDRED_MILLIS.sleep();
try (RaftClient c2 = cluster.createClient(leader.getId(), RetryPolicies.noRetry())) {
// more write requests should get ResourceUnavailableException
final SimpleMessage message = new SimpleMessage("err");
testFailureCase("send should fail", () -> c2.io().send(message), ResourceUnavailableException.class);
testFailureCase("sendAsync should fail", () -> c2.async().send(message).get(), ExecutionException.class, ResourceUnavailableException.class);
// more watch requests should get ResourceUnavailableException
final long watchIndex = watchBase + watchElementLimit;
testFailureCase("sendWatch should fail", () -> c2.io().watch(watchIndex, ReplicationLevel.ALL), ResourceUnavailableException.class);
testFailureCase("sendWatchAsync should fail", () -> c2.async().watch(watchIndex, ReplicationLevel.ALL).get(), ExecutionException.class, ResourceUnavailableException.class);
}
// complete futures from applyTransaction
toBeCompleted.forEach(Runnable::run);
// check replies
for (CompletableFuture<RaftClientReply> f : writeFutures) {
final RaftClientReply reply = getWithDefaultTimeout(f);
Assert.assertTrue(reply.isSuccess());
}
}
}
use of org.apache.ratis.protocol.RaftClientReply in project incubator-ratis by apache.
the class WatchRequestTests method runTestWatchRequestAsyncChangeLeader.
static void runTestWatchRequestAsyncChangeLeader(TestParameters p) throws Exception {
final Logger LOG = p.log;
final MiniRaftCluster cluster = p.cluster;
final int numMessages = p.numMessages;
// blockFlushStateMachineData a follower so that no transaction can be ALL_COMMITTED
final List<RaftServer.Division> followers = cluster.getFollowers();
final RaftServer.Division blockedFollower = followers.get(ThreadLocalRandom.current().nextInt(followers.size()));
LOG.info("block follower {}", blockedFollower.getId());
SimpleStateMachine4Testing.get(blockedFollower).blockFlushStateMachineData();
final List<CompletableFuture<RaftClientReply>> replies = new ArrayList<>();
final List<CompletableFuture<WatchReplies>> watches = new ArrayList<>();
p.sendRequests(replies, watches);
Assert.assertEquals(numMessages, replies.size());
Assert.assertEquals(numMessages, watches.size());
// since only one follower is blocked commit, requests can be committed MAJORITY and ALL but not ALL_COMMITTED.
checkMajority(replies, watches, LOG);
TimeUnit.SECONDS.sleep(1);
assertNotDone(watches.stream().map(CompletableFuture::join).map(w -> w.allCommitted));
// Now change leader
RaftTestUtil.changeLeader(cluster, cluster.getLeader().getId());
// unblock follower so that the transaction can be replicated and committed to all.
SimpleStateMachine4Testing.get(blockedFollower).unblockFlushStateMachineData();
LOG.info("unblock follower {}", blockedFollower.getId());
checkAll(watches, LOG);
}
Aggregations