use of org.apache.ratis.client.RaftClient in project incubator-ratis by apache.
the class RaftAsyncTests method testStaleReadAsync.
@Test
public void testStaleReadAsync() throws Exception {
final int numMesssages = 10;
final CLUSTER cluster = getFactory().newCluster(NUM_SERVERS, properties);
try (RaftClient client = cluster.createClient()) {
cluster.start();
RaftTestUtil.waitForLeader(cluster);
// submit some messages
final List<CompletableFuture<RaftClientReply>> futures = new ArrayList<>();
for (int i = 0; i < numMesssages; i++) {
final String s = "m" + i;
LOG.info("sendAsync " + s);
futures.add(client.sendAsync(new RaftTestUtil.SimpleMessage(s)));
}
Assert.assertEquals(numMesssages, futures.size());
RaftClientReply lastWriteReply = null;
for (CompletableFuture<RaftClientReply> f : futures) {
lastWriteReply = f.join();
Assert.assertTrue(lastWriteReply.isSuccess());
}
futures.clear();
// Use a follower with the max commit index
final RaftPeerId leader = lastWriteReply.getServerId();
LOG.info("leader = " + leader);
final Collection<CommitInfoProto> commitInfos = lastWriteReply.getCommitInfos();
LOG.info("commitInfos = " + commitInfos);
final CommitInfoProto followerCommitInfo = commitInfos.stream().filter(info -> !RaftPeerId.valueOf(info.getServer().getId()).equals(leader)).max(Comparator.comparing(CommitInfoProto::getCommitIndex)).get();
final RaftPeerId follower = RaftPeerId.valueOf(followerCommitInfo.getServer().getId());
LOG.info("max follower = " + follower);
// test a failure case
testFailureCaseAsync("sendStaleReadAsync(..) with a larger commit index", () -> client.sendStaleReadAsync(new RaftTestUtil.SimpleMessage("" + (numMesssages + 1)), followerCommitInfo.getCommitIndex(), follower), StateMachineException.class, IndexOutOfBoundsException.class);
// test sendStaleReadAsync
for (int i = 1; i < followerCommitInfo.getCommitIndex(); i++) {
final int query = i;
LOG.info("sendStaleReadAsync, query=" + query);
final Message message = new RaftTestUtil.SimpleMessage("" + query);
final CompletableFuture<RaftClientReply> readFuture = client.sendReadOnlyAsync(message);
final CompletableFuture<RaftClientReply> staleReadFuture = client.sendStaleReadAsync(message, followerCommitInfo.getCommitIndex(), follower);
futures.add(readFuture.thenApply(r -> getMessageContent(r)).thenCombine(staleReadFuture.thenApply(r -> getMessageContent(r)), (expected, computed) -> {
try {
LOG.info("query " + query + " returns " + LogEntryProto.parseFrom(expected).getSmLogEntry().getData().toStringUtf8());
} catch (InvalidProtocolBufferException e) {
throw new CompletionException(e);
}
Assert.assertEquals("log entry mismatch for query=" + query, expected, computed);
return null;
}));
}
JavaUtils.allOf(futures).join();
} finally {
cluster.shutdown();
}
}
use of org.apache.ratis.client.RaftClient in project incubator-ratis by apache.
the class RaftBasicTests method testRequestTimeout.
public static void testRequestTimeout(boolean async, MiniRaftCluster cluster, Logger LOG, RaftProperties properties) throws InterruptedException, IOException, ExecutionException {
LOG.info("Running testRequestTimeout");
waitForLeader(cluster);
long time = System.currentTimeMillis();
try (final RaftClient client = cluster.createClient()) {
// Get the next callId to be used by the client
long callId = RaftClientTestUtil.getCallId(client);
// Create an entry corresponding to the callId and clientId
// in each server's retry cache.
cluster.getServerAliveStream().forEach(raftServer -> RetryCacheTestUtil.getOrCreateEntry(raftServer.getRetryCache(), client.getId(), callId));
// The retry is successful when the retry cache entry for the corresponding callId and clientId expires.
if (async) {
CompletableFuture<RaftClientReply> replyFuture = client.sendAsync(new SimpleMessage("abc"));
replyFuture.get();
} else {
client.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.
TimeDuration duration = TimeDuration.valueOf(System.currentTimeMillis() - time, TimeUnit.MILLISECONDS);
TimeDuration retryCacheExpiryDuration = RaftServerConfigKeys.RetryCache.expiryTime(properties);
Assert.assertTrue(duration.compareTo(retryCacheExpiryDuration) >= 0);
}
}
use of org.apache.ratis.client.RaftClient in project incubator-ratis by apache.
the class RaftExceptionBaseTest method testStaleReadException.
@Test
public void testStaleReadException() throws Exception {
RaftTestUtil.waitForLeader(cluster);
try (RaftClient client = cluster.createClient()) {
final RaftPeerId follower = cluster.getFollowers().iterator().next().getId();
testFailureCase("sendStaleRead(..) with a large commit index", () -> client.sendStaleRead(Message.EMPTY, 1_000_000_000L, follower), StateMachineException.class, StaleReadException.class);
}
}
use of org.apache.ratis.client.RaftClient in project incubator-ratis by apache.
the class RaftExceptionBaseTest method testLogAppenderBufferCapacity.
@Test
public void testLogAppenderBufferCapacity() throws Exception {
RaftTestUtil.waitForLeader(cluster);
final RaftPeerId leaderId = cluster.getLeader().getId();
final RaftClient client = cluster.createClient(leaderId);
byte[] bytes = new byte[8192];
Arrays.fill(bytes, (byte) 1);
SimpleMessage msg = new SimpleMessage(new String(bytes));
try {
client.send(msg);
Assert.fail("Expected StateMachineException not thrown");
} catch (StateMachineException sme) {
Assert.assertTrue(sme.getMessage().contains("exceeds the max buffer limit"));
}
}
use of org.apache.ratis.client.RaftClient in project incubator-ratis by apache.
the class RaftExceptionBaseTest method testNotLeaderExceptionWithReconf.
@Test
public void testNotLeaderExceptionWithReconf() throws Exception {
Assert.assertNotNull(RaftTestUtil.waitForLeader(cluster));
final RaftPeerId leaderId = cluster.getLeader().getId();
final RaftClient client = cluster.createClient(leaderId);
// enforce leader change
RaftPeerId newLeader = RaftTestUtil.changeLeader(cluster, leaderId);
// also add two new peers
// add two more peers
MiniRaftCluster.PeerChanges change = cluster.addNewPeers(new String[] { "ss1", "ss2" }, true);
// trigger setConfiguration
LOG.info("Start changing the configuration: {}", Arrays.asList(change.allPeersInNewConf));
try (final RaftClient c2 = cluster.createClient(newLeader)) {
RaftClientReply reply = c2.setConfiguration(change.allPeersInNewConf);
Assert.assertTrue(reply.isSuccess());
}
LOG.info(cluster.printServers());
RaftClientRpc rpc = client.getClientRpc();
RaftClientReply reply = null;
// it is possible that the remote peer's rpc server is not ready. need retry
for (int i = 0; reply == null && i < 10; i++) {
try {
reply = rpc.sendRequest(cluster.newRaftClientRequest(ClientId.randomId(), leaderId, new SimpleMessage("m1")));
} catch (IOException ignored) {
Thread.sleep(1000);
}
}
Assert.assertNotNull(reply);
Assert.assertFalse(reply.isSuccess());
final NotLeaderException nle = reply.getNotLeaderException();
Objects.requireNonNull(nle);
Assert.assertEquals(newLeader, nle.getSuggestedLeader().getId());
Collection<RaftPeer> peers = cluster.getPeers();
RaftPeer[] peersFromReply = reply.getNotLeaderException().getPeers();
Assert.assertEquals(peers.size(), peersFromReply.length);
for (RaftPeer p : peersFromReply) {
Assert.assertTrue(peers.contains(p));
}
reply = client.send(new SimpleMessage("m2"));
Assert.assertTrue(reply.isSuccess());
client.close();
}
Aggregations