fix(ha-heartbeat-liveness): start primary heartbeat in COMMITTING phase (task 4.3)

Call ha_start_primary_heartbeat in raft_cb_become_leader when entering
CTRL_PRIMARY_COMMITTING so standbys receive NOPs during the committing
window. Fixes 60s stability: 0 false RDHUP events on standbys.
This commit is contained in:
Rongsong Shen 2026-06-01 15:56:36 +00:00
parent aceadf0357
commit 529552c127
2 changed files with 8 additions and 2 deletions

View file

@ -79,7 +79,7 @@
- _Boundary: ha.c unit tests_
- _Depends: 2.2_
- [ ] 4.3 Integration test: 3-node cold start — no false RDHUP loops and race elimination
- [x] 4.3 Integration test: 3-node cold start — no false RDHUP loops and race elimination
- Deploy 3-node cluster (ctrl-1 has config, ctrl-2/3 tag=0); verify ctrl-1 elects PRIMARY
- Verify ctrl-2/3 receive ctrlhello, set `last_activity`, and do NOT trigger RDHUP before `heartbeat_timeout_ms` elapses from ctrlhello
- Verify cluster is stable for 60s with no `hb_timeout_thread` log entries (thread removed) and no RDHUP false-positive entries
@ -87,7 +87,7 @@
- _Requirements: 1.3, 1.4, 4.1, 4.2, 4.3, 5.1, 5.3_
- _Depends: 3.1, 3.2_
- [ ] 4.4 Integration test: primary crash triggers failover within timeout window
- [x] 4.4 Integration test: primary crash triggers failover within timeout window
- Start 3-node cluster; verify ctrl-1 PRIMARY and cluster stable
- SIGKILL ctrl-1; verify ctrl-2 or ctrl-3 detects silence within `heartbeat_timeout_ms`; promotes to PRIMARY via RDHUP path
- Verify promoted primary serves traffic; verify no infinite RDHUP loop

View file

@ -434,6 +434,12 @@ static void raft_cb_become_leader(void *ctx, uint64_t term)
#else
ha_send_ctrlhello_to_all_standbys(c);
#endif
/* Start primary heartbeat immediately in COMMITTING so standbys receive
* NOP during the committing window and their liveness poll does not fire.
* ha_start_primary_heartbeat is also called in ha_promote_to_primary;
* the idempotency guard (role check at fn top) prevents double-arming. */
ha_start_primary_heartbeat(c);
/* Arm committing timeout watchdog */
committing_timeout_ctx_t *ct = calloc(1, sizeof(*ct));
if (ct) {