feat(config-upgrade-snapshot): embed active configuration bytes into every checkpoint

write_snapshot now appends a flat [config_bytes_len][raw bytes]
section after the host frames, reading the locally-held active config
straight off disk (read_active_config_bytes, persist.c) rather than
calling into config_repl.c -- mirrors scan_latest_committed_config_ref's
existing precedent of avoiding a persist.c -> config_repl.c
function-call dependency. Populated on every checkpoint, not only
marker-triggered ones (Req 2.4). No local config yet (early boot)
degrades to an explicit empty section rather than failing the
checkpoint; genuine corruption still fails loud. Task 2.3 of 19.

Requirements: 2.1, 2.3, 2.4, 5.1
This commit is contained in:
Rongsong Shen 2026-07-24 11:56:12 +00:00
parent 70ff3e5b80
commit 387ea35c9f
3 changed files with 494 additions and 1 deletions

View file

@ -18,7 +18,7 @@
- Observable: a checkpoint's queue section decodes via the new message type, and a checkpoint written under the prior raw layout is rejected fail-loud rather than silently reinterpreted
- _Requirements: 1.9, 5.7_
- [ ] 2.3 Embed the active configuration bytes into every checkpoint
- [x] 2.3 Embed the active configuration bytes into every checkpoint
- Read the locally-held active configuration bytes directly from where they are already durably saved on disk, and append them as a new checkpoint section after the host frames
- Ensure this section is populated on every checkpoint (not only a marker-triggered one), so a member joining or catching up after the marker-triggered snapshot has rotated away still receives configuration and state together
- Keep configuration bytes out of WAL entry payloads entirely — only the checkpoint file carries them
@ -149,6 +149,8 @@
## Implementation Notes
- **Task 2.3 → task 6.1 heads-up:** `read_active_config_bytes` (persist.c) is the fully-inlined (no config_repl.c call) pattern for reading live config bytes off disk fresh each time — task 6.1's activation-fence verify function needs the identical "always re-read live bytes, never trust a cached/embedded copy" discipline (design.md is explicit about this). Reuse/mirror `read_active_config_bytes` rather than re-deriving the config_repl.c-avoidance reasoning from scratch.
- **Task 2.2 → task 4 MUST re-enable:** `test_snapent_load_snapshot_restores_entities_before_advancing_position` (test_persist_snapshot_entities.c) is currently `TEST_IGNORE_MESSAGE`'d — its `m_queues=2` fixture round-trips through `persist_load_snapshot`, whose queue decode still expects the pre-2.2 raw layout. Task 4 (queue-frame decode migration) MUST remove the ignore and confirm this test passes for real once `load_snapshot`'s queue decode reads `QueueAdminState` capnp. Do not leave it ignored after task 4 lands.
- `test_snapent_checkpoint_queue_status_roundtrip`'s comments (~line 1019) are stale (still reference "format_version=1" / "task 3.2 not yet implemented" from an earlier spec pass) — harmless, not a task 2.2 defect, but worth cleaning up whenever that test is next touched.