fix: bug-1445 -- first-boot promotion check races its own first replay
raft_cb_become_leader()'s eligibility gate read persist_apply_resource_fenced() before this process's own first cluster_init_phase2()/persist_recover()/replay_wal() call ever ran -- so a node whose first-ever replay hit a resource-exhaustion apply failure could still become CTRL_PRIMARY, because the fence that replay would engage didn't exist yet when the gate checked it. Every LATER promotion evaluation was already correctly protected; this was a narrow gap specific to a process's single very-first election. Fix: re-check persist_apply_resource_fenced() immediately after cluster_init_phase2() completes on first boot, refusing promotion (same WARN + ha_arm_promotion_fence_timer() + return pattern as the existing refusal branch) if that first replay just engaged the fence. Confirmed ha_elect_evaluate_and_signal (the other election path) is dead in production for the promotion outcome -- every live call site of handle_request_vote_reply passes vote_granted=0 since bug-828 redirected real grant recording to the record-only, non-signaling ha_record_vote_reply -- so raft_cb_become_leader is the sole live promotion path and this fix's scope is complete. TDD: new test test_first_boot_promotion_evaluates_own_first_replay_fence wires ha_phase2_hook to actually call persist_recover(), reproducing production ordering exactly. RED-confirmed against the unfixed code at the precise predicted assertion; GREEN-confirmed after the fix. Full controller_unit_test regression (bundles every HA-adjacent testsuite/test_*.c) green, 0 new failures. Originally documented (not fixed) in job-array-single-wal-record task 7.2's Implementation Notes; logged as bug-1445 and fixed here, outside that spec's own task list per its persist.c-only boundary.
This commit is contained in:
parent
5ddc20f359
commit
ff01db3665
4 changed files with 227 additions and 6 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"feature_name": "job-array-single-wal-record",
|
||||
"created_at": "2026-07-09T17:20:00Z",
|
||||
"updated_at": "2026-07-17T09:47:00Z",
|
||||
"updated_at": "2026-07-17T10:45:00Z",
|
||||
"language": "en",
|
||||
"phase": "implementation-complete",
|
||||
"approvals": {
|
||||
|
|
@ -23,8 +23,9 @@
|
|||
"validate_impl": {
|
||||
"decision": "GO",
|
||||
"validated_at": "2026-07-17T09:47:00Z",
|
||||
"known_limitations": [
|
||||
"bug-1445: first-boot promotion-ordering gap -- a node's very first promotion evaluation in a fresh process runs before that node's own first persist_recover()/replay_wal() call, so the Live Apply Resource Fence is invisible to that one specific check. Every promotion evaluation after a process's first one is protected. Out of this spec's persist.c-only boundary; tracked in .wolf/buglog.json, not fixed in this spec."
|
||||
"known_limitations": [],
|
||||
"resolved_limitations": [
|
||||
"bug-1445 (first-boot promotion-ordering gap) fixed 2026-07-17 in src/controller/ha.c (raft_cb_become_leader), outside this spec's own task list -- see .wolf/buglog.json for full detail. TDD-verified (RED/GREEN) with a dedicated test plus a full controller_unit_test regression pass."
|
||||
],
|
||||
"prior_decision": {
|
||||
"decision": "GO",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue