public void testCandidateTransitionsToFollowerOnRejection() throws Throwable { serverState.onStateChange( state -> { if (state == RaftServer.State.FOLLOWER) resume(); }); runOnServer( () -> { for (MemberState member : serverState.getCluster().getActiveMembers()) { Server server = transport.server(); server .listen( member.getAddress(), c -> { c.handler( VoteRequest.class, request -> CompletableFuture.completedFuture( VoteResponse.builder().withTerm(2).withVoted(false).build())); }) .thenRunAsync(this::resume); } }); await(1000, serverState.getCluster().getActiveMembers().size()); runOnServer( () -> { int self = serverState.getAddress().hashCode(); serverState.setTerm(1); state.startElection(); assertEquals(serverState.getTerm(), 2L); assertEquals(serverState.getLastVotedFor(), self); }); await(1000); }
@Override public CompletableFuture<Void> close() { return local.close().thenCompose(v -> remote.close()); }
@Override public CompletableFuture<Void> listen(Address address, Consumer<Connection> listener) { Assert.notNull(address, "address"); Assert.notNull(listener, "listener"); return local.listen(address, listener).thenCompose(v -> remote.listen(address, listener)); }