feat(ha-term-safety): retire term-0 repl_broadcast live send; carry leader term on replication (task 3.4)

Closes bug-990: the live replicator repl_broadcast wire-encoded term=0
(entry.term was never set), so standbys persisted hdr.term=0 and took the
legacy direct-apply path instead of the library (term,lsn) intake. Now the
live broadcast and catch-up streamer carry the leader's real term + AE prev
tuple; ha_apply_wal_catchup_entry routes every term-carrying entry through
raft_on_append_entries_request -> on_persist_entry (leader term stamped),
retiring the term-0 direct-apply. Standbys now persist the leader's real term
and reconcile by (term,lsn); the live commit chain is end-to-end.

848/849/850 + persist-before-ACK + commit-barrier + bug-960 preserved.
Proven at integration level; the definitive live STRICT_TERM failover run is
env-blocked here (bug-924 overlayfs) and recommended on a real fs.
This commit is contained in:
Rongsong Shen 2026-06-22 15:45:14 +00:00
parent 87242aa8e9
commit efe621c124
11 changed files with 307 additions and 45 deletions

View file

@ -478,6 +478,14 @@ static void wal_entry_to_wire(struct capn_segment *cs,
/* ha-term-safety task 3.2: carry the entry's term stamp so the standby
* intake persists the LEADER's recorded term (R1.3/R1.4), not a substitute. */
w->term = e->term;
/* ha-term-safety task 3.4: carry the AppendEntries prev tuple + leaderCommit
* PER SUB-ENTRY so a multi-entry catch-up batch is routable through the
* library one entry at a time (each sub-entry's prev tuple differs; the
* top-level container can hold only one). For a single-entry broadcast this
* is redundant with the top-level metadata but harmless. */
w->prevLogIndex = e->prev_log_index;
w->prevLogTerm = e->prev_log_term;
w->leaderCommit = e->leader_commit;
if (e->raw_payload && e->raw_payload_len > 0) {
capn_list8 pl = capn_new_list8(cs, (int)e->raw_payload_len);
capn_setv8(pl, 0, e->raw_payload, (int)e->raw_payload_len);