feat(ha-heartbeat-committed-propagation): add reconcile-free ha_observe_heartbeat_committed (task 2.1)

Strict-monotonic updater for a standby's learned committed position: advance
last_known_committed_lsn only when strictly greater (zero/lower no-op), set the
config tag together (tag-before-lsn release ordering for reader safety). No
ha_rejoin_reconcile, no truncation, no other mutation (Req 2.1-2.3, 3.1, 3.3).
4 revert-detecting unit tests; controller suite 0 failures.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-06-20 11:52:18 +00:00
parent 282a82ff7e
commit 8bfa861be2
6 changed files with 273 additions and 1 deletions

View file

@ -17,7 +17,7 @@
- _Boundary: libxce sender_
- [ ] 2. Standby consume (reconcile-free, term-guarded, monotonic)
- [ ] 2.1 Add the reconcile-free monotonic updater `ha_observe_heartbeat_committed`
- [x] 2.1 Add the reconcile-free monotonic updater `ha_observe_heartbeat_committed`
- Add `ha_observe_heartbeat_committed(cluster_t* c, uint64_t committed_lsn, uint64_t committed_config_tag)` (`ha.c`, declared in `ha.h`): advance `last_known_committed_lsn` only when the carried LSN is strictly greater (monotonic; atomic), advancing `last_known_committed_config_tag` together with it; no-op when `<=` current or zero. It must NOT call `ha_rejoin_reconcile`, truncate the WAL, or modify any produced/persisted committed state.
- TDD: unit tests assert advance-on-higher (LSN + config tag updated), no-op on equal/lower/zero, config tag never regresses independently, and — critically — that the call performs no WAL truncation / no reconcile and mutates nothing beyond `last_known_committed_*`.
- Observable: the unit tests go red → green; the no-truncation / no-mutation assertions hold.