- public void applyServerConfiguration(ServerConfigurationPayload serverConfig) {
- Set<String> currentPeers = new HashSet<>(context.getPeerIds());
- for(ServerInfo server: serverConfig.getServerConfig()) {
- if(!getId().equals(server.getId())) {
- VotingState votingState = server.isVoting() ? VotingState.VOTING: VotingState.NON_VOTING;
- if(!currentPeers.contains(server.getId())) {
- context.addToPeers(server.getId(), null, votingState);
- } else {
- context.getPeerInfo(server.getId()).setVotingState(votingState);
- currentPeers.remove(server.getId());
+ // Check whether we should update the term. In case of half-connected nodes, we want to ignore RequestVote
+ // messages, as the candidate is not able to receive our response.
+ protected boolean shouldUpdateTerm(final RaftRPC rpc) {
+ if (!(rpc instanceof RequestVote)) {
+ return true;
+ }
+
+ final RequestVote requestVote = (RequestVote) rpc;
+ log.debug("{}: Found higher term in RequestVote rpc, verifying whether it's safe to update term.", logName());
+ final Optional<Cluster> maybeCluster = context.getCluster();
+ if (!maybeCluster.isPresent()) {
+ return true;
+ }
+
+ final Cluster cluster = maybeCluster.get();
+
+ final Set<Member> unreachable = cluster.state().getUnreachable();
+ log.debug("{}: Cluster state: {}", logName(), unreachable);
+
+ for (Member member : unreachable) {
+ for (String role : member.getRoles()) {
+ if (requestVote.getCandidateId().startsWith(role)) {
+ log.debug("{}: Unreachable member: {}, matches candidateId in: {}, not updating term", logName(),
+ member, requestVote);
+ return false;