Skip to content

Commit

Permalink
Reply pre_vote_result instead of transitioning to follower
Browse files Browse the repository at this point in the history
  • Loading branch information
sile committed May 21, 2024
1 parent da3d732 commit e6bbd1a
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 11 deletions.
15 changes: 6 additions & 9 deletions src/ra_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -919,22 +919,19 @@ handle_candidate(#pre_vote_rpc{term = Term} = Msg,
handle_candidate(#request_vote_rpc{}, State = #{current_term := Term}) ->
Reply = #request_vote_result{term = Term, vote_granted = false},
{candidate, State, [{reply, Reply}]};
handle_candidate(#pre_vote_rpc{term = Term, last_log_index = PeerLastIdx} = Msg,
handle_candidate(#pre_vote_rpc{term = Term, last_log_index = PeerLastIdx} = PreVote,
#{current_term := CurTerm,
cfg := #cfg{log_id = LogId}} = State0)
cfg := #cfg{log_id = LogId}} = State)
when Term =:= CurTerm ->
{LastIdx, _} = last_idx_term(State0),
%% This clause is necessary to prevent the liveness issue reported in https://github.com/rabbitmq/ra/issues/439
{LastIdx, _} = last_idx_term(State),
case PeerLastIdx > LastIdx of
true ->
%% To prevent the liveness issue reported in https://github.com/rabbitmq/ra/issues/439,
%% if a candidate member receives a `#pre_vote_rpc{}` with a higher last index,
%% it should transition to the follower state.
?INFO("~ts: candidate pre_vote_rpc with higher last index received ~b -> ~b",
[LogId, LastIdx, PeerLastIdx]),
State = update_term_and_voted_for(Term, undefined, State0),
{follower, State, [{next_event, Msg}]};
process_pre_vote(candidate, PreVote, State);
false ->
{candidate, State0, []}
{candidate, State, []}
end;
handle_candidate(#pre_vote_rpc{}, State) ->
%% just ignore pre_votes that aren't of a higher term
Expand Down
5 changes: 3 additions & 2 deletions test/ra_server_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1943,8 +1943,9 @@ candidate_receives_pre_vote(_Config) ->
{follower, #{current_term := 6}, _}
= ra_server:handle_candidate(PreVoteRpc#pre_vote_rpc{term = 6}, State),

% candidate abdicates for higher index
{follower, #{}, _}
% candidate replies `#pre_vote_result{vote_granted=true}` for higher index
{candidate, #{},
[{reply, #pre_vote_result{token = Token, vote_granted = true}}]}
= ra_server:handle_candidate(PreVoteRpc#pre_vote_rpc{last_log_index = 4}, State),

ok.
Expand Down

0 comments on commit e6bbd1a

Please sign in to comment.