fix(ha-repl-hardening): n_peers count and single-node safe_lsn (task 6.5)
- Fix ha_start_election_async: ha->n_peers = n_other (other peers), not candidates_count (total including self). The standby_converged[] array is indexed by peer index, so the bound must be n_other. - Fix ha_compute_safe_committed_lsn: return self_lsn for n_peers==0 (prevents WAL truncation on single-node re-election). - Integration test: 3-node cluster reaches CTRL_PRIMARY via majority convergence within ~20s; no degraded-mode WARN in logs.
This commit is contained in:
parent
345d51dd61
commit
e10cf9a6fc
2 changed files with 13 additions and 7 deletions
|
|
@ -233,7 +233,7 @@
|
|||
- All tests pass under ASAN
|
||||
- _Requirements: 4.1, 4.2, 4.3, 4.4_
|
||||
|
||||
- [ ] 6.5 Integration test: 3-node startup via majority convergence
|
||||
- [x] 6.5 Integration test: 3-node startup via majority convergence
|
||||
- Requires task 5.3 (`committing_timeout_ms=60000`) deployed so timeout does not fire during test
|
||||
- Deploy via `/xce-deploy-ha`; all 3 nodes start within 15s
|
||||
- Verify primary enters `CTRL_PRIMARY` via majority-convergence INFO log (not committing timeout WARN)
|
||||
|
|
|
|||
|
|
@ -3041,23 +3041,29 @@ void ha_start_election_async(ha_state_t *ha, cluster_t *c,
|
|||
raft_init(&ha->raft, &rcfg);
|
||||
}
|
||||
|
||||
/* Step 1: store peer count for ha_repl_ack_received quorum calculation */
|
||||
ha->n_peers = n_peers;
|
||||
|
||||
/* Step 2: transition to CTRL_ELECTING before firing RPCs.
|
||||
/* Step 1: transition to CTRL_ELECTING before firing RPCs.
|
||||
* raft_start_election fires on_become_leader / on_send_vote_request below;
|
||||
* the role must already be ELECTING so ha_dispatch_gate() admits vote RPCs. */
|
||||
atomic_store_explicit(&ha->role, (int32_t)CTRL_ELECTING, memory_order_release);
|
||||
INFO("HA FSM: → CTRL_ELECTING (async, n_peers=%d)", n_peers);
|
||||
|
||||
/* Step 3: pre-allocate ha_elect_ctx_t so raft_cb_send_vote_request can
|
||||
/* Step 2: pre-allocate ha_elect_ctx_t so raft_cb_send_vote_request can
|
||||
* read my_tag/my_lsn from it when building the capnp VoteRequest payload.
|
||||
* Vote counting is now owned by the raft library; this ctx is only a
|
||||
* metadata carrier for tag/lsn. For multi-node elections it is kept alive
|
||||
* until all per-peer vote_ep_ctx_t endpoints finish (iomgr lifetime).
|
||||
* For single-node, raft_start_election fires on_become_leader immediately
|
||||
* so no ctx reads occur after return. */
|
||||
* so no ctx reads occur after return.
|
||||
*
|
||||
* n_other = other-node count (self excluded). standby_converged[] is
|
||||
* indexed by votes_idx (relative, 0 .. n_other-1), so ha->n_peers must
|
||||
* store n_other, NOT the total candidates_count. Both
|
||||
* ha_check_majority_convergence and ha_repl_ack_received read ha->n_peers
|
||||
* as "number of OTHER nodes". */
|
||||
int n_other = (n_peers > 1) ? n_peers - 1 : 0;
|
||||
|
||||
/* Store other-peer count for quorum calculations */
|
||||
ha->n_peers = n_other;
|
||||
ha_elect_ctx_t *ctx = calloc(1, sizeof(*ctx) +
|
||||
(size_t)n_other * sizeof(ctx->votes[0]));
|
||||
if (!ctx) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue