Commit 9632faa6 authored by Georgios Bitzes's avatar Georgios Bitzes
Browse files

raft: activate pre-vote, add intermediate state check before real vote

parent fdc6a9bd
Pipeline #1563038 passed with stages
in 111 minutes and 52 seconds
......@@ -6,14 +6,14 @@
- The mechanism meant to provide an early warning for potential ``MANIFEST``
corruption was flaky, and would sometimes report a problem where none existed.
Many thanks to Franck Eyraud (JRC) for the bug report concerning erroneous ``MANIFEST``-related
warning.
### Improvements
- Implementation of an optional part of raft, pre-vote. This should prevent partitioned,
or otherwise flaky rejoining servers from triggering needless elections. A node will first issue
an experimental voting round before advancing its term, and start campaigning
for real only if it has a good chance of winning.
or otherwise flaky rejoining servers from triggering unnecessary and disruptive elections.
A node will first issue an experimental voting round before advancing its term, and start campaigning
for earnest only if it has a good chance of winning.
Many thanks to Franck Eyraud (JRC) for the bug report concerning erroneous ``MANIFEST``-related
warning.
## 0.4.2 (2020-03-12)
......
......@@ -136,7 +136,26 @@ void RaftDirector::runForLeader() {
return;
}
// advance the term by one, become a candidate.
//----------------------------------------------------------------------------
// vvvvvvvvvvvvvvvvvvvvvvv OPTIONAL PART OF RAFT vvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//----------------------------------------------------------------------------
ElectionOutcome prevoteOutcome = RaftElection::performPreVote(votereq, state, contactDetails);
if(prevoteOutcome == ElectionOutcome::kVetoed) {
lastHeartbeatBeforeVeto = lastHeartbeat;
qdb_info("Pre-vote round for term " << snapshot->term + 1 << " resulted in a veto. This means, the next leader of this cluster cannot be me. Stopping election attempts until I receive a heartbeat.");
}
if(prevoteOutcome != ElectionOutcome::kElected) return;
if(!state.isSnapshotCurrent(snapshot.get())) {
qdb_info("Raft state has progressed since successful pre-vote round, retrying from scratch.");
return;
}
//----------------------------------------------------------------------------
// ^^^^^^^^^^^^^^^^^^^^^^^ OPTIONAL PART OF RAFT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//----------------------------------------------------------------------------
// pre-vote succeeded, advance the term by one, become a candidate.
if(!state.observed(snapshot->term+1, {})) return;
if(!state.becomeCandidate(snapshot->term+1)) return;
......
......@@ -811,7 +811,7 @@ TEST_F(Raft_Director, late_consensus) {
// verify the node tried to ascend, and failed
RaftStateSnapshotPtr snapshot = state(0)->getSnapshot();
ASSERT_GE(snapshot->term, 1);
ASSERT_EQ(snapshot->term, 0);
ASSERT_TRUE(snapshot->leader.empty());
ASSERT_TRUE( (snapshot->status == RaftStatus::FOLLOWER) || (snapshot->status == RaftStatus::CANDIDATE) );
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment