Skip to content

Commit

Permalink
raft: enter candidate state immediately when starting a singleton clu…
Browse files Browse the repository at this point in the history
…ster

When a node starts it does not immediately becomes a candidate since it
waits to learn about already existing leader and randomize the time it
becomes a candidate to prevent dueling candidates if several nodes are
started simultaneously.

If a cluster consist of only one node there is no point in waiting
before becoming a candidate though because two cases above cannot
happen. This patch checks that the node belongs to a singleton cluster
where the node itself is the only voting member and becomes candidate
immediately. This reduces the starting time of a single node cluster
which are often used in testing.

Message-Id: <[email protected]>
  • Loading branch information
Gleb Natapov authored and tgrabiec committed Mar 4, 2022
1 parent 1c5ab5d commit 108e7fc
Show file tree
Hide file tree
Showing 3 changed files with 5 additions and 6 deletions.
6 changes: 5 additions & 1 deletion raft/fsm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ fsm::fsm(server_id id, term_t current_term, server_id voted_for, log log,
logger.trace("fsm[{}]: starting, current term {}, log length {}, commit index {}", _my_id, _current_term, _log.last_idx(), _commit_idx);

// Init timeout settings
reset_election_timeout();
if (_log.get_configuration().current.size() == 1 && _log.get_configuration().can_vote(_my_id)) {
become_candidate(_config.enable_prevoting);
} else {
reset_election_timeout();
}
}

fsm::fsm(server_id id, term_t current_term, server_id voted_for, log log,
Expand Down
2 changes: 0 additions & 2 deletions test/raft/etcd_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,6 @@ BOOST_AUTO_TEST_CASE(test_single_node_commit) {
raft::log log{raft::snapshot_descriptor{.config = cfg}};
raft::fsm fsm(id1, term_t{}, server_id{}, std::move(log), trivial_failure_detector, fsm_cfg);

make_candidate(fsm);
BOOST_CHECK(fsm.is_leader()); // Single node skips candidate state
output = fsm.get_output();
BOOST_CHECK(output.log_entries.size() == 1);
Expand Down Expand Up @@ -670,7 +669,6 @@ BOOST_AUTO_TEST_CASE(test_single_node_pre_candidate) {
raft::log log1{raft::snapshot_descriptor{.config = cfg}};
raft::fsm fsm1(id1, term_t{}, server_id{}, std::move(log1), trivial_failure_detector, fsm_cfg_pre);

make_candidate(fsm1);
BOOST_CHECK(fsm1.is_leader());
}

Expand Down
3 changes: 0 additions & 3 deletions test/raft/fsm_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,6 @@ void test_election_single_node_helper(raft::fsm_config fcfg) {
raft::log log{raft::snapshot_descriptor{.config = cfg}};
raft::fsm fsm(id1, term_t{}, server_id{}, std::move(log), trivial_failure_detector, fcfg);

BOOST_CHECK(fsm.is_follower());

election_timeout(fsm);

// Immediately converts from leader to follower if quorum=1
Expand Down Expand Up @@ -1150,7 +1148,6 @@ BOOST_AUTO_TEST_CASE(test_confchange_a_to_b) {
log.emplace_back(make_lw_shared<raft::log_entry>(B.add_entry(raft::configuration({A_id}))));
log.stable_to(log.last_idx());
raft::fsm B_1(B_id, B.get_current_term(), B_id, std::move(log), trivial_failure_detector, fsm_cfg);
BOOST_CHECK(B_1.is_follower());
election_timeout(B_1);
communicate(A, B_1);
BOOST_CHECK(B_1.is_follower());
Expand Down

0 comments on commit 108e7fc

Please sign in to comment.