feat(election-iomgr-refactor): wire RDHUP failover to ha_start_election_async — task 5.2

This commit is contained in:
Rongsong Shen 2026-05-30 12:43:02 +00:00
parent 2e5681387a
commit 31a54043d5
3 changed files with 168 additions and 7 deletions

View file

@ -2371,6 +2371,16 @@ ctrl_role_t am_i_primary_quorum(ha_state_t *ha,
#ifdef XCE_TESTING
int (*ha_tcp_connect_hook)(const char *host, int port) = NULL;
/*
* ha_rdhup_election_hook: test-only seam for ha_start_election_async in the
* RDHUP failover path. When non-NULL, ha_on_primary_ctrl_fd_rdhup() calls
* this instead of the real ha_start_election_async(). Req 6.3, 6.5, 9.3.
*/
void (*ha_rdhup_election_hook)(ha_state_t *ha, cluster_t *c,
int n_peers, xce_candidate_t **peers,
uint64_t my_config_tag, uint64_t my_lsn,
const char *my_name) = NULL;
#endif
/* ha_tcp_connect_raw: non-blocking connect + poll, returns connected fd or -errno */
@ -2551,7 +2561,10 @@ void ha_on_primary_ctrl_fd_rdhup(ha_state_t *ha, cluster_t *c)
if (committed > 0)
persist_truncate_wal_above(&c->persist, committed);
/* Fire election — am_i_primary_quorum handles the vote and role assignment */
/* Fire async election — ha_start_election_async is non-blocking (Req 6.3, 6.5).
* ha->phase2_done==1 at this point (set after initial startup election), so
* ha_elect_evaluate_and_signal will skip cluster_init_phase2 and go directly
* to CTRL_PRIMARY_COMMITTING (Req 9.3). */
if (c->myconf && c->myconf->peers_cfg.candidates_count > 0) {
const xce_cluster_config_t *cfg = &c->myconf->peers_cfg;
int n = cfg->candidates_count > 0 ? cfg->candidates_count - 1 : 0;
@ -2565,12 +2578,16 @@ void ha_on_primary_ctrl_fd_rdhup(ha_state_t *ha, cluster_t *c)
uint64_t my_tag = c->myconf->config_version_tag;
uint64_t my_lsn = atomic_load_explicit(&c->persist.committed_lsn,
memory_order_acquire);
ctrl_role_t new_role = am_i_primary_quorum(ha, np, peer_ptrs, my_tag, my_lsn,
c->myconf ? c->myconf->name : "");
if (new_role == CTRL_PRIMARY)
INFO("HA: RDHUP recovery → CTRL_PRIMARY (Req 6.8)");
else
INFO("HA: RDHUP recovery → CTRL_STANDBY, reconnecting (Req 6.8)");
const char *my_name = c->myconf ? c->myconf->name : "";
#ifdef XCE_TESTING
if (ha_rdhup_election_hook != NULL) {
ha_rdhup_election_hook(ha, c, np, peer_ptrs, my_tag, my_lsn, my_name);
} else {
ha_start_election_async(ha, c, np, peer_ptrs, my_tag, my_lsn, my_name);
}
#else
ha_start_election_async(ha, c, np, peer_ptrs, my_tag, my_lsn, my_name);
#endif
}
}