feat(controller-status): carry election time on the heartbeat (task 7.3)

The primary echoes its own last_known_elected_at_ms on every outgoing
heartbeat (threaded through xce_ha_heartbeat_req's existing scalar-arg
plumbing, alongside term/committed_lsn/committed_config_tag); a standby
processing a received heartbeat (ha_consume_heartbeat_committed, the sole
production call site) stores it unconditionally into its own
last_known_elected_at_ms, reconcile-free -- no other HA field moves.
ha_observe_heartbeat_committed itself is untouched; the new store sits
next to its call site, not inside it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
Rongsong Shen 2026-09-16 06:03:03 +00:00
parent 21ae00b375
commit 30adc52ea3
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
9 changed files with 252 additions and 33 deletions

View file

@ -44,10 +44,12 @@ extern int (*ha_reconnect_connect_hook)(cluster_t *c, int peer_idx);
extern int primary_heartbeat_fn_for_test(cluster_t *c);
extern int standby_ep_ctx_build_for_test(endpoint_t *ep, ha_state_t *ha,
cluster_t *c, int peer_idx);
/* ha_heartbeat_req_hook: per-standby stamp hook (endpoint, term, committed_lsn, tag). */
/* ha_heartbeat_req_hook: per-standby stamp hook (endpoint, term, committed_lsn,
* tag, elected_at_ms). */
extern int (*ha_heartbeat_req_hook)(endpoint_t *ep, uint64_t term,
uint64_t committed_lsn,
uint64_t committed_config_tag);
uint64_t committed_config_tag,
uint64_t elected_at_ms);
extern int (*ha_nop_req_hook)(endpoint_t *ep);
@ -195,9 +197,11 @@ static int ps_heal_nop_hook(endpoint_t *ep)
* standby_endpoints so it's never reached. Only installed during partition;
* it must never block the tick. */
static int partition_hb_hook(endpoint_t *ep, uint64_t term,
uint64_t committed_lsn, uint64_t committed_config_tag)
uint64_t committed_lsn, uint64_t committed_config_tag,
uint64_t elected_at_ms)
{
(void)ep; (void)term; (void)committed_lsn; (void)committed_config_tag;
(void)elected_at_ms;
atomic_fetch_add(&g_survivor_nops, 1);
return 0;
}