feat(ha-commit-engine): honest write-admission quorum accounting (task 4.2)

repl_active_standby_count: registry truth (ep != NULL && !in_catch_up)
under r->lock. ha_state_t gains repl back-pointer (wired at init by
task 5.3); ha_has_write_quorum uses registry truth when wired, exact
legacy fallback when NULL; formula unchanged. Test 29 (wired gate,
catch-up-only standby → NOT_READY, admits after clear) captured RED
pre-fix. 29/29 group tests; suite at the 3-failure baseline.
This commit is contained in:
Rongsong Shen 2026-06-11 22:28:44 +00:00
parent b2598823c0
commit c9154bd5cc
6 changed files with 92 additions and 11 deletions

View file

@ -1513,11 +1513,21 @@ static bool ha_has_write_quorum(ha_state_t *ha)
if (ha->n_peers <= 1)
return true;
/* Count connected standbys. standby_endpoints is populated by
* raft_cb_become_leader (promoted vote eps) and on_standby_connected
* (late joiners); removed by error handlers. */
int connected = ha->standby_endpoints
/* Count standbys able to receive new log entries. When the replicator
* back-pointer is wired (task 5.3 init), use registry truth: slots with
* ep != NULL && !in_catch_up under r->lock (Req 3.1-3.3) — catch-up
* members cannot ACK new entries, so they must not count toward write
* admission. NULL back-pointer (legacy contexts) falls back to the
* standby_endpoints count populated by raft_cb_become_leader (promoted
* vote eps) and on_standby_connected (late joiners); removed by error
* handlers. */
int connected;
if (ha->repl) {
connected = repl_active_standby_count(ha->repl);
} else {
connected = ha->standby_endpoints
? ha->standby_endpoints->count : 0;
}
/* Need at least n_peers/2 connected standbys to achieve quorum.
* Integer division: n_peers/2 for n_peers=3 → 1 standby minimum. */