feat(raft-commit-safety): commit_index state + on_commit_advanced callback + init (tasks 1.1, 1.2, 2.1)

1.1: raft_state_t.commit_index (monotonic, ==WAL LSN, <=log_len, advanced only via
raft_advance_commit, untouched by AE reply) + raft_config_t.initial_commit_index.
1.2: on_commit_advanced(ctx, commit_index) REQUIRED callback — fired only on strict
advance, a TRIGGER for the controller commit barrier (never does durability itself).
2.1: raft_init requires it (-EINVAL if NULL) + restores commit_index from
initial_commit_index. raft_advance_commit prototype declared (impl in 3.2).

Coupled callback wiring to keep the required-callback ripple green: sim wires
sim_on_commit_advanced (+per-node commit_index mirror & fire-count), all test cbs
builders set it, raft_sim_restart_node restores the durable commit position. Vote
signatures unchanged; no commit-advance logic yet. ASAN green (224 tests).
This commit is contained in:
Rongsong Shen 2026-06-21 23:11:17 +00:00
parent 3d6dc9cc56
commit 3ba6f03a9e
5 changed files with 170 additions and 7 deletions

View file

@ -8,14 +8,14 @@
## 1. Header contract: commit_index, on_commit_advanced, raft_advance_commit, freshness signatures
- [ ] 1.1 Extend `raft.h` with the commit-index state and restore field
- [x] 1.1 Extend `raft.h` with the commit-index state and restore field
- Add `uint64_t commit_index;` to `raft_state_t`
- Add `uint64_t initial_commit_index;` to `raft_config_t` (restored committed LSN at boot, default 0; library never reads storage — consistent with `initial_term`/`initial_log_len`)
- Observable completion: `raft.h` compiles; `sizeof(raft_state_t)` grows by the new field; no entry-byte storage added
- _Requirements: 1.1, 1.5_
- _Boundary: raft.h_
- [ ] 1.2 Add the `on_commit_advanced` REQUIRED callback to `raft_callbacks_t` (verbatim contract)
- [x] 1.2 Add the `on_commit_advanced` REQUIRED callback to `raft_callbacks_t` (verbatim contract)
- Declare `void on_commit_advanced(void *ctx, uint64_t commit_index)` with the exact signature from design.md / brief
- Document it as REQUIRED, fired only on strict advance, and as a TRIGGER for the existing commit barrier (never performs durability itself)
- Observable completion: the function-pointer member exists in `raft_callbacks_t` with the verbatim signature; header doc comment matches the Authoritative shared contract
@ -34,7 +34,7 @@
## 2. Init validation and commit-index restore
- [ ] 2.1 RED+GREEN: `raft_init` requires `on_commit_advanced` and restores `initial_commit_index`
- [x] 2.1 RED+GREEN: `raft_init` requires `on_commit_advanced` and restores `initial_commit_index`
- Test: `raft_init` returns `-EINVAL` when `on_commit_advanced` is NULL; returns 0 when present; `s->commit_index == cfg->initial_commit_index` after init
- Implement the NULL check in `raft_init` (mirroring the existing required-callback checks); restore `s->commit_index = cfg->initial_commit_index`
- Observable completion: new `-EINVAL` test case passes; restore assertion passes; existing election + log-replication init tests still green