feat(raft-library): task 3.2 — raft_start_election with single-node shortcircuit; 4 tests

This commit is contained in:
Rongsong Shen 2026-05-31 05:30:00 +00:00
parent 1aa7db4583
commit 4955fa3805
3 changed files with 318 additions and 3 deletions

View file

@ -51,8 +51,51 @@ int raft_init(raft_state_t *s, const raft_config_t *cfg)
int raft_start_election(raft_state_t *s)
{
(void)s;
return 0;
/* Guard: reject if already CANDIDATE or LEADER */
if (s->role == RAFT_CANDIDATE || s->role == RAFT_LEADER)
return -EALREADY;
/* Increment term and record self-vote before any RPCs (split-brain prevention) */
s->term++;
s->voted_for = s->self_idx;
s->voted_for_term = s->term;
s->votes_granted = 1; /* self-vote */
s->replies_received = 0;
s->election_decided = 0;
if (s->cbs->on_trace)
s->cbs->on_trace(s->ctx, "term_update", NULL);
if (s->cbs->on_trace)
s->cbs->on_trace(s->ctx, "self_vote", NULL);
/* Persist new term and self-vote before sending any RPCs */
s->cbs->on_persist(s->ctx, s->term, s->self_idx);
if (s->cbs->on_trace)
s->cbs->on_trace(s->ctx, "election_start", NULL);
/* Single-node shortcircuit: win immediately, no RPCs, no timeout */
if (s->n_peers == 1) {
s->role = RAFT_LEADER;
s->election_decided = 1;
s->cbs->on_become_leader(s->ctx, s->term);
return RAFT_ELECTED_IMMEDIATELY;
}
/* Multi-node: transition to CANDIDATE */
s->role = RAFT_CANDIDATE;
/* Send RequestVote to all peers except self */
for (int i = 0; i < s->n_peers; i++) {
if (i == s->self_idx)
continue;
s->cbs->on_send_vote_request(s->ctx, i, s->term);
}
/* Schedule election timeout watchdog */
s->cbs->on_schedule_timeout(s->ctx, s->election_timeout_ms);
return RAFT_OK;
}
int raft_on_vote_request(raft_state_t *s, int from_idx, uint64_t term,