forked from lei.chen/myxce
fix(ha): bug-1421 close term-desync AE-reject blindspot in HA election
A primary never learns of a follower's higher term via AppendEntries-reject responses: ha_raft_on_repl_ack only routes AE replies through raft_on_append_entries_reply for success=1 ACKs, and that function itself drops any reply whose term != s->term (raft.c stale-term drop) before it could adopt a higher term anyway. Net effect: once a follower outpaces a stale primary's term, every AppendEntries the primary sends is rejected forever and it can never regain write-quorum — a permanent election livelock (surfaced as "no primary elected at term>8" in HA soak testing). Adds two fallback term-discovery vectors that fire regardless of AE-reject outcome: - StateReport heartbeat-reply now carries the standby's current term (controller.capnp, typemap.h) so the primary learns a higher term on every convergence cycle. - New raft_on_higher_term_observed() mirrors the UpdateTerm step (strictly greater-than only; touches term/voted_for/role; persists before notifying on_become_follower) and is wired into both the heartbeat state-report path and the WAL-NACK path in repl_ack_decode_and_dispatch. Validated: 265 controller + 287 lib unit tests pass; 10-round sequential and chaotic HA soaks both PASS with zero job loss and full leadership coverage.
This commit is contained in:
parent
0941cf9649
commit
327dbb9bb3
5 changed files with 62 additions and 1 deletions
|
|
@ -818,6 +818,7 @@ struct ReplEnvelope $C.mapname("capnp_repl_envelope_t") {
|
|||
struct StateReport $C.mapname("state_report_t") {
|
||||
appliedLsn @0 :UInt64 $C.mapname("applied_lsn"); # standby's last applied WAL LSN
|
||||
configTag @1 :UInt64 $C.mapname("config_tag"); # standby's current config version tag
|
||||
term @2 :UInt64 $C.mapname("term"); # standby's current raft term (bug-1421 term-discovery)
|
||||
}
|
||||
|
||||
struct RequestVoteRequest $C.mapname("request_vote_req_t") {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue