myxce/src/controller
Rongsong Shen 34ab78d72d fix(ha): close permanent quorum-loss deadlock on log-conflicted standby (bug-1479)
Chaotic election churn (config-upgrade-snapshot task 8.6's force_elect_node
rotation) can leave a standby log-conflicted after a rejoin. Fixing this
needed three compounding layers, each unit-green but still failing the
identical live scenario until the next layer landed:

1. ha_raft_on_repl_nack (ha.c/ha.h): routes a WAL-ACK NACK into the raft
   library's nextIndex backoff and immediately repl_start_catchup's the
   standby at the corrected position, instead of the 16-strike silent
   eviction with no catch-up driver after it. Correct from the start, but
   live soak still failed identically: nothing ever produced the NACK this
   code was waiting for.

2. Standby-side NACK sending: ha_apply_term_entry_via_library's logOk-reject
   path now calls a new ha_send_wal_ack_reply_ex(..., success=0) instead of
   silently dropping the reject. ha_send_wal_ack_reply had hardcoded
   success=1 unconditionally -- the only WalAckReply sender in the
   controller -- making (1)'s NACK-routing correct but unreachable dead
   code. New ha_wal_ack_send_hook (XCE_TESTING) lets a unit test observe
   the NACK without a live endpoint. Live-confirmed the NACK now reaches
   the primary -- but the scenario still failed for a third reason.

3. ha_compute_repl_stream_ceiling_lsn (ha.c/ha.h): ha_stream_wal_to_standby's
   catch-up range was hard-bounded at committed_lsn, which can never advance
   in this exact scenario because advancing it requires an ACK from the very
   standby that's stuck catching up (2-of-3 alive, this standby is the only
   path to a new majority) -- a self-referential deadlock. Widens the
   STREAM_WAL ceiling (and the convergence check gating it) to the leader's
   own log tail, matching raft.tla's real AppendEntries semantics
   (leaderCommit is advisory, never a send-cap), while reusing bug-1478's
   exact guard so this doesn't reopen that trap (never widen onto a trailing
   local-only checkpoint's own unstreamable LSN).

Verification: controller_unit_test 1053/1053 PASS, clean twice, including
new regression tests for all three layers (test_config_repl.c,
test_term_safety_adapter.c, test_ha_role.c), each RED-confirmed against its
pre-fix behavior before the real fix was restored. Three successive live
run-ha-soak.sh --config-upgrade re-runs tracked each layer landing; the
final run passed end-to-end -- all 3 force_elect_node rounds succeeded
(ctrl-2: 3/3 jobs acked term=6; ctrl-3: 3/3 jobs acked term=7, never
previously reached), zero materialized-state divergence, zero job loss.
Unblocks config-upgrade-snapshot task 8.6.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 04:11:32 +00:00
..
include feat(config-upgrade-snapshot): restore host admin-state frame safely (create-if-missing) 2026-07-24 12:48:28 +00:00
testsuite fix(ha): close permanent quorum-loss deadlock on log-conflicted standby (bug-1479) 2026-07-29 04:11:32 +00:00
apiserver.c fix(schema): rename struct Data -> XceData to unshadow capnp builtin blob type 2026-07-22 09:22:04 +00:00
CLAUDE.md docs(steering): sync steering + xce-audit-invariants skill after Jul 13-18 work 2026-07-19 08:14:11 +00:00
cluster.c feat(config-upgrade-snapshot): live config-upgrade soak infra + fix bug-1468/bug-1469 (task 8.6) 2026-07-25 15:48:20 +00:00
commit.c feat(raft-apply-decoupling): ordered live apply pump activates apply_committed_entry (task 6.1) 2026-07-04 19:00:43 +00:00
config_repl.c fix(ha): close permanent catch-up wedge from duplicated replication-target formula (bug-1478) 2026-07-28 09:53:20 +00:00
config_repl.h fix(config): serialize load_primary_config against concurrent invocations (bug-1476) 2026-07-28 08:13:54 +00:00
ctrl_metrics.c feat: P3-7 ctrl_metrics — 7 atomic counters/gauges + descriptor table + persist wiring 2026-05-08 00:04:06 +00:00
ctrlstatus.c feat(ha-heartbeat-committed-propagation): migrate last_known_committed_config_tag to _Atomic (task 1.1) 2026-06-20 11:27:46 +00:00
dataex.c fix(persist): zero nresvals_to_sched after free_name_val_list 2026-05-20 09:39:07 +00:00
egress.c feat(ha-convergence-recovery): commit-gated scheduler egress — submit_lsn tagging + watermark gate (task 1.2) 2026-06-14 02:33:36 +00:00
ha.c fix(ha): close permanent quorum-loss deadlock on log-conflicted standby (bug-1479) 2026-07-29 04:11:32 +00:00
ha.h fix(ha): close permanent quorum-loss deadlock on log-conflicted standby (bug-1479) 2026-07-29 04:11:32 +00:00
ha_convergence.c fix(controller): bug-1450/1451 offload delaymgr-inline blocking work to the slow lane 2026-07-19 08:14:00 +00:00
job.c merge 2026-07-23 12:35:10 +08:00
join.c fix(controller): bug-1433 async-thread fdatasync block + bug-1434 committed_lsn CAS race 2026-07-11 12:16:28 +00:00
main.c fix(config): serialize load_primary_config against concurrent invocations (bug-1476) 2026-07-28 08:13:54 +00:00
meson.build feat(config-upgrade-snapshot): add bug-857 regression test, correct design.md (task 8.5) 2026-07-25 10:44:14 +00:00
misc.c save works 2026-03-05 16:03:37 +08:00
myapp.c fix(ha): retry cluster_init_phase2 on failure instead of latching phase2_done unconditionally (bug-1477) 2026-07-28 13:25:48 +00:00
myconf.c fix(config): serialize load_primary_config against concurrent invocations (bug-1476) 2026-07-28 08:13:54 +00:00
opget.c fix(schema): rename struct Data -> XceData to unshadow capnp builtin blob type 2026-07-22 09:22:04 +00:00
opupd.c save works 2026-03-03 16:49:26 +08:00
persist.c fix(ha): close permanent standby catch-up wedge after a WAL_CHECKPOINT boundary (bug-1475) 2026-07-28 04:48:53 +00:00
queue.c feat(ha-commit-barrier-rollout): commit-first-then-reply in all four handlers (task 3.2) 2026-06-12 10:28:25 +00:00
repl.c fix(ha): close permanent quorum-loss deadlock on log-conflicted standby (bug-1479) 2026-07-29 04:11:32 +00:00
reply.c fix(persist): zero nresvals_to_sched after free_name_val_list 2026-05-20 09:39:07 +00:00
resources.c update controller code 2025-11-05 16:58:57 +08:00
sched.c feat(controller): wire real limits.yaml config through cluster_config 2026-07-23 04:24:01 +00:00
slowlane.c feat(raft-drive-async): SlowLane bounded executor for long blocking I/O (task 1.2) 2026-06-26 05:24:00 +00:00
startup_validation.c feat(ha-heartbeat-liveness): add validate_heartbeat_config startup check (task 1.2) 2026-06-01 12:26:29 +00:00
task.c save works 2026-03-04 18:18:53 +08:00
worker.c fix(worker): replicate admin host-control status updates to standbys (bug-1472) 2026-07-26 04:06:42 +00:00