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.
38 lines
1.5 KiB
JSON
38 lines
1.5 KiB
JSON
{
|
|
"feature_name": "job-array-single-wal-record",
|
|
"created_at": "2026-07-09T17:20:00Z",
|
|
"updated_at": "2026-07-17T10:45:00Z",
|
|
"language": "en",
|
|
"phase": "implementation-complete",
|
|
"approvals": {
|
|
"requirements": {
|
|
"generated": true,
|
|
"approved": true
|
|
},
|
|
"design": {
|
|
"generated": true,
|
|
"approved": true
|
|
},
|
|
"tasks": {
|
|
"generated": true,
|
|
"approved": true
|
|
}
|
|
},
|
|
"ready_for_implementation": true,
|
|
"blocked_on": [],
|
|
"validate_impl": {
|
|
"decision": "GO",
|
|
"validated_at": "2026-07-17T09:47:00Z",
|
|
"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",
|
|
"validated_at": "2026-07-16T02:10:00Z",
|
|
"reopened_at": "2026-07-16T06:15:00Z",
|
|
"reopen_reason": "User directed all of this feature's own open residual gaps be fixed (2026-07-16): bug-1443 (bulk-insert partial-visibility), task 4.2's boot-replay fence gap, and task 5.3b's bounded leak. Added as Phase 7 (tasks 7.1-7.3) in tasks.md. Unrelated pre-existing bugs 1437/1438 explicitly excluded from this reopening per user's scope decision.",
|
|
"note": "bug-1443 was closed by task 7.1 (commit dcf9f39); superseded by this validation's fresh GO."
|
|
}
|
|
}
|
|
}
|