feat(ha-repl-hardening): wire config push from decision loop (task 3.3)

ha_dispatch_repl_action_for_standby() calls push_config_to_standbys()
when PUSH_CONFIG decision. Hook seam for unit tests. Wired into
repl_ack_decode_and_dispatch after ha_process_standby_state.
oldest_wal_lsn=0 placeholder documented for task 3.4.
This commit is contained in:
Rongsong Shen 2026-06-04 17:23:46 +00:00
parent a475ef621f
commit d1c7872d73
4 changed files with 258 additions and 1 deletions

View file

@ -529,6 +529,36 @@ void ha_start_election_async(ha_state_t *ha, cluster_t *c,
*/
void ha_repl_ack_received(ha_state_t *ha, cluster_t *c);
/*
* ha_dispatch_repl_action_for_standby: evaluate the replication decision for
* one standby and execute the resulting action.
*
* Reads ha->standby_reported_tag[peer_idx] and ha->standby_reported_lsn[peer_idx]
* (stored by ha_process_standby_state on the previous call), calls
* ha_evaluate_repl_action, and if the result is HA_REPL_PUSH_CONFIG:
* - In production builds: calls push_config_to_standbys(c, …).
* - In XCE_TESTING builds: calls ha_repl_push_config_for_standby_hook(c, peer_idx)
* if the hook is non-NULL.
*
* One action per heartbeat cycle per standby (design §Unified Heartbeat-Driven
* Protocol). Other actions (SEND_SNAPSHOT, STREAM_WAL) are stubs returning 0
* pending Tasks 3.4–3.5; CONVERGED is a no-op.
*
* peer_idx — 0-based index into ha->standby_reported_* arrays
* committed_tag — primary's committed config_tag (from c->myconf or test fixture)
* committed_lsn — primary's committed WAL LSN (from c->persist or test fixture)
* oldest_wal_lsn— oldest retained WAL LSN (0 = all WAL retained, skip snapshot)
*
* Returns 0 on success; negative on internal error.
* Requirements: 1.4 (ha-repl-hardening spec)
*/
int ha_dispatch_repl_action_for_standby(ha_state_t *ha,
cluster_t *c,
int peer_idx,
uint64_t committed_tag,
uint64_t committed_lsn,
uint64_t oldest_wal_lsn);
/*
* ha_send_ctrlhello_to_all_standbys: iterate ha->standby_endpoints and send
* an OP_hello CtrlHelloRequest to each connected standby.
@ -565,6 +595,21 @@ extern int (*ha_send_ctrlhello_hook)(void *c);
*/
extern int (*ha_push_config_hook)(void *c);
/*
* ha_repl_push_config_for_standby_hook: test-only seam for the per-standby
* config push triggered by the heartbeat-reply decision loop (Task 3.3).
*
* When non-NULL, ha_dispatch_repl_action_for_standby() calls this INSTEAD OF
* push_config_to_standbys() when the decision is HA_REPL_PUSH_CONFIG, so unit
* tests can verify the wiring without requiring a real cluster_t or network.
*
* Signature: int hook(void *c, int peer_idx)
* c — cluster_t* (may be NULL in test mode)
* peer_idx — 0-based index of the standby that triggered the push
* Requirements: 1.4 (ha-repl-hardening)
*/
extern int (*ha_repl_push_config_for_standby_hook)(void *c, int peer_idx);
/*
* ha_tcp_connect_hook: test-only seam for the raw TCP connect inside
* ha_find_and_connect_to_primary. When non-NULL, the function calls this