feat(ha-prevote): implement pure candidate-side PreVote start (task 2.2)
raft_begin_pre_vote: compute prospective term (term+1) locally without persisting, arm the pre_vote_* tally with a self-grant, NULL-safely probe each non-self peer, return RAFT_PRE_VOTE_WON for single-node else RAFT_OK. Stays FOLLOWER, schedules no timeout, mutates no persistent state. 6 RED-first tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
722fee5323
commit
6db912b2a9
3 changed files with 254 additions and 1 deletions
|
|
@ -229,6 +229,45 @@ int raft_on_pre_vote_request(raft_state_t *s, int from_idx, uint64_t cand_term)
|
|||
return RAFT_GRANT;
|
||||
}
|
||||
|
||||
int raft_begin_pre_vote(raft_state_t *s)
|
||||
{
|
||||
/* Pre-image of raft_start_election: probe peers + tally a self-grant, but
|
||||
* STRIP every persistent side effect. Per the header INVARIANT (Req 1.2,
|
||||
* 1.3, 6.2) this function MUST NOT touch s->term, s->voted_for,
|
||||
* s->voted_for_term, or s->role, and MUST NOT call on_persist. The node
|
||||
* stays FOLLOWER throughout the round; CANDIDATE happens later in the
|
||||
* unchanged raft_start_election once the PreVote round is WON. */
|
||||
|
||||
/* Prospective term is a LOCAL value only — never assigned to s->term and
|
||||
* never persisted (this is the whole point of PreVote). */
|
||||
uint64_t prospective_term = s->term + 1;
|
||||
|
||||
/* Reset and arm the round tally on the raft state. Self always grants. */
|
||||
s->pre_vote_in_progress = 1;
|
||||
s->pre_votes_granted = 1; /* self-grant */
|
||||
memset(s->pre_vote_replies, 0, sizeof(s->pre_vote_replies));
|
||||
|
||||
if (s->cbs->on_trace)
|
||||
s->cbs->on_trace(s->ctx, "pre_vote_start", NULL);
|
||||
|
||||
/* Single-node: no peers, the self-grant is already a majority. Win
|
||||
* immediately and let the caller proceed to raft_start_election. */
|
||||
if (s->n_peers == 1)
|
||||
return RAFT_PRE_VOTE_WON;
|
||||
|
||||
/* Probe every peer except self with the prospective term (NULL-checked:
|
||||
* if the callback is unset, the caller owns the transport). */
|
||||
if (s->cbs->on_send_pre_vote_request) {
|
||||
for (int i = 0; i < s->n_peers; i++) {
|
||||
if (i == s->self_idx)
|
||||
continue;
|
||||
s->cbs->on_send_pre_vote_request(s->ctx, i, prospective_term);
|
||||
}
|
||||
}
|
||||
|
||||
return RAFT_OK;
|
||||
}
|
||||
|
||||
int raft_on_vote_reply(raft_state_t *s, int from_idx, int granted, uint64_t term)
|
||||
{
|
||||
(void)from_idx;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue