RaftEx.Server.Election
(raft_ex v0.1.0)
View Source
Raft leader election implementation with pre-vote support.
This module handles the election process including:
- Pre-vote phase: Checks if an election would succeed before incrementing term
- Candidate phase: Actual voting with term increment
- Vote request/reply handling
- Quorum evaluation
- Election timeout management
Election Flow
- Pre-Vote: Candidate probes peers without incrementing term
- Vote Request: If pre-vote succeeds, increment term and request votes
- Vote Reply: Peers grant vote if candidate's log is up-to-date
- Win Condition: Candidate wins if it receives votes from majority
Pre-Vote Benefits
Pre-vote prevents a partitioned node from disrupting the cluster by:
- Not incrementing its term until it knows it can win
- Avoiding unnecessary term increases that would force leader re-election
- Allowing the node to catch up before starting a real election
Summary
Functions
Check if it's still possible to win the election.
Evaluate election result based on current votes.
Handle a pre-vote reply from a peer.
Handle an incoming pre-vote request.
Handle a vote reply from a peer.
Handle an incoming vote request.
Start an election (pre-vote or candidate phase).
Get the number of votes needed to win.
Types
@type election_context() :: %{ state: election_state(), term: RaftEx.Types.term_num(), votes_received: MapSet.t(RaftEx.Types.server_id()), total_voters: non_neg_integer(), last_log_index: RaftEx.Types.index(), last_log_term: RaftEx.Types.term_num() }
@type election_result() :: :won | :lost | :ongoing
@type election_state() :: :pre_vote | :candidate
Functions
@spec can_still_win?(non_neg_integer(), non_neg_integer()) :: boolean()
Check if it's still possible to win the election.
Returns true if there are enough outstanding votes to reach majority.
@spec evaluate_election_result(election_context()) :: election_result()
Evaluate election result based on current votes.
Returns :won, :lost, or :ongoing.
@spec handle_pre_vote_reply( RaftEx.Types.PreVoteResult.t(), election_context(), map(), RaftEx.Types.server_id() ) :: {boolean(), election_context(), [term()]}
Handle a pre-vote reply from a peer.
Returns {should_start_election, updated_context, effects}.
Handle an incoming pre-vote request.
Returns {vote_granted, effects}.
@spec handle_vote_reply( RaftEx.Types.RequestVoteResult.t(), election_context(), map(), RaftEx.Types.server_id() ) :: {election_result(), election_context(), [term()]}
Handle a vote reply from a peer.
Returns {election_result, updated_context, effects}.
Handle an incoming vote request.
Returns {vote_granted, updated_state, effects}.
@spec start_election(election_state(), map()) :: {election_context(), [term()]}
Start an election (pre-vote or candidate phase).
Returns {election_context, effects} where effects include RPCs to send to peers.
@spec votes_needed(non_neg_integer()) :: non_neg_integer()
Get the number of votes needed to win.
Returns the majority count.