fix(ha): close permanent catch-up wedge from duplicated replication-target formula (bug-1478)
Two independent call sites duplicated target = max(committed_lsn, last_written): ha.c's heartbeat/stateReport dispatch (repl_ack_decode_and_ dispatch) and config_repl.c's catchup_derive_target (used by the ACK-driven catch-up continuation path). Once config-upgrade-snapshot's marker-triggered checkpoint advances last_written one LSN past an already-committed committed_lsn (the checkpoint's own consumed, never-replicated LSN slot), the unconditional max() permanently wedges every standby's catch-up target at an unreachable value -- the primary re-streams an empty range every heartbeat forever. Extracted the shared, pure ha_compute_repl_target_lsn(committed_lsn, last_written) (ha.h/ha.c), which only falls back to last_written on genuine committed_lsn==0 bootstrap, and pointed both call sites at it so they can never disagree again. Fixing the second call site exposed three pre-existing tests in test_convergence_verification.c that hardcoded the old buggy formula's output as their expected target; updated their fixture values (committed_lsn 4->9, matching appended_lsn) to decouple them from the now-fixed edge case, which already has dedicated pure-function coverage in test_ha_role.c. GREEN: full controller_unit_test suite = 1040 tests, 0 failures, clean across multiple runs. Live-verified via run-ha-soak.sh --config-upgrade-wal-trim (18 jobs, zero job loss, ctrl-1 reconverged 3-of-3 using the preserved floor segment) -- unblocks config-upgrade-snapshot task 8.9.
This commit is contained in:
parent
71223ec712
commit
102e263cce
9 changed files with 850 additions and 20 deletions
|
|
@ -1127,6 +1127,24 @@ void ha_process_standby_state(ha_state_t *ha, int peer_idx,
|
|||
uint64_t reported_tag, uint64_t reported_lsn,
|
||||
uint64_t committed_tag, uint64_t committed_lsn);
|
||||
|
||||
/*
|
||||
* ha_compute_repl_target_lsn: the replication/convergence target used by
|
||||
* ha_dispatch_repl_action_for_standby's heartbeat-driven decision — normally
|
||||
* committed_lsn itself, falling back to last_written (the raw locally-
|
||||
* appended WAL tip) ONLY when committed_lsn is genuinely stuck at 0
|
||||
* (cluster bootstrap, before any standby has ever acked anything).
|
||||
*
|
||||
* bug-1478: the fallback must NOT apply once committed_lsn is already > 0 —
|
||||
* see ha.c's doc comment on this function for the full mechanism (a
|
||||
* local-only WAL_CHECKPOINT trailing an already-advancing committed_lsn
|
||||
* otherwise leaks an unstreamable/unreachable target into every subsequent
|
||||
* heartbeat decision, permanently wedging catch-up).
|
||||
*
|
||||
* Pure, side-effect-free.
|
||||
*/
|
||||
uint64_t ha_compute_repl_target_lsn(uint64_t committed_lsn,
|
||||
uint64_t last_written);
|
||||
|
||||
/* ── Task 3.5c: Standby snapshot receive handler ──────────────────────────── */
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue