feat(ha-repl-hardening): majority-convergence → CTRL_PRIMARY transition (task 5.2)

- Add ha_check_majority_convergence() in ha.c: counts standby_converged[],
  promotes CTRL_PRIMARY_COMMITTING → CTRL_PRIMARY when all standbys converge
- Threshold: n_peers (all standbys) per spec test cases; single-node satisfies immediately
- Called from repl_ack_decode_and_dispatch() before replication dispatch
- Logs INFO "majority converged (N/M standbys) → CTRL_PRIMARY" (Req 7.4)
- Three unit tests: 1/2 converged → stays COMMITTING; 2/2 → PRIMARY; single-node → immediate
- Fix ha.h comment: clarify double-promotion prevention via vtask context, not CAS
This commit is contained in:
Rongsong Shen 2026-06-05 04:42:53 +00:00
parent d13010e4e0
commit 534bfd68fe
4 changed files with 218 additions and 1 deletions

View file

@ -377,6 +377,26 @@ void ha_process_standby_state(ha_state_t *ha, int peer_idx,
uint64_t reported_tag, uint64_t reported_lsn,
uint64_t committed_tag, uint64_t committed_lsn);
/* ── Task 5.2: Majority-convergence → PRIMARY transition ─────────────────────
*
* ha_check_majority_convergence: count converged standbys and promote to
* CTRL_PRIMARY when the threshold is met while role == CTRL_PRIMARY_COMMITTING.
*
* Threshold: ha->n_peers (all standbys must converge).
* Single-node (n_peers=0): threshold=0 → satisfied immediately.
*
* Double-promotion is prevented by the single-threaded vtask context; a role
* check (CTRL_PRIMARY_COMMITTING) is sufficient.
* Logs INFO "majority converged (N/M standbys) → CTRL_PRIMARY" (Req 7.4).
* If c != NULL, registers persistence hooks and arms periodic heartbeat.
*
* Called from repl_ack_decode_and_dispatch after ha_process_standby_state.
*
* Requirements: 2.3, 2.4, 6.3, 6.5 (ha-repl-hardening spec)
* Boundary: Controller FSM (ha.c)
*/
void ha_check_majority_convergence(ha_state_t *ha, cluster_t *c);
/* ── Task 3.5c: Standby snapshot receive handler ──────────────────────────── */
/*