examples: add long-running soak driver with consistency check (#22)#26
Merged
Conversation
Adds a soak example for DataWal that exercises put / delete / fsync / compact over a wall-clock budget, samples Linux RSS / fd / segment counts to a CSV, and asserts that the live keydir matches an in-memory oracle after a drop + reopen cycle. The soak is intentionally not part of CI and not part of the default test suite. It only has to compile; running it is opt-in. There is no claim about durability under power loss, OS crash, or hardware failure and no QPS target. Refs #22 hardening umbrella PR-4. What ships: - crates/datawal-core/examples/soak.rs (~495 LOC). Two modes (synthetic / real), env-var driven, CSV output. Mode `real` reads three JSONL files via DATAWAL_SOAK_INPUT_{SMALL,MEDIUM,LARGE}. Mode `synthetic` uses an in-process PRNG. Both share the same weighted-put / 5%-delete / fsync-every-1k / compact-every-N-ops inner loop. Final consistency check compares reopened keydir against the oracle; exit 0 iff equal. - crates/datawal-core/examples/gen_soak_fixtures.rs (~180 LOC). Deterministic SplitMix64-seeded JSONL generator. Committed fixtures under tests/fixtures/soak/ are reproducible byte for byte from the same seeds (small=100x512B, medium=100x3KiB, large=20x64KiB; ~2.2MB total). - docs/soak.md. Documents synthetic vs real, env vars, CSV columns, exit codes, what the soak is and is not. - scripts/run_soak_real.sh. Refuses to run without explicit DATAWAL_SOAK_INPUT_{SMALL,MEDIUM,LARGE} pointing at readable files. No internal paths baked in. What stays the same: - WIRE_VERSION = 1, six corpus fixtures untouched. - Public surface unchanged. No new types, no new methods. - No new runtime dependencies. The example uses serde, serde_json, base64 and anyhow, all already in workspace.dependencies. - CI signals unchanged. Examples compile via cargo build but are not executed. Local validation: - cargo fmt --all -- --check clean - cargo clippy --workspace --all-targets clean - cargo test --workspace --all-targets 124 tests green - cargo doc --workspace --no-deps clean (RUSTDOCFLAGS=-D) - cargo build --workspace --examples clean - 8-second synthetic smoke: RSS stable at 5.6 MB, fd count 7, segment count 1, live keys oscillating in 90-95 band, ~1 GB written, final check OK, exit 0. Not in this PR: - dm-flakey injection - differential comparison against a second implementation - memory-leak instrumentation - concurrent fuzz - CI invocation of the soak Those remain on the Tier 2 hardening shortlist.
This was referenced May 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lands the soak slot of the Tier 1 hardening track from umbrella #22. Adds a long-running
DataWaldriver that exercises put / delete / fsync / compact under a wall-clock budget, samples Linux RSS / fd / segment counts to a CSV, and asserts the live keydir matches an in-memory oracle after a drop + reopen cycle.Refs #22 hardening umbrella PR-4.
What this is, what it isn't
What ships
crates/datawal-core/examples/soak.rs(~495 LOC). Two modes (--mode synthetic/--mode real), env-var driven, CSV output at${DATAWAL_SOAK_LOG_DIR}/soak.csv. Inner loop: weighted 70/25/5 small/medium/large stream selection, ~95% put / ~5% delete, explicitfsyncevery 1k ops,compact_to+ swap-and-reopen everyROTATE_EVERY * COMPACT_EVERY_ROTATIONSops (defaults 5000 × 4 = 20000). Final consistency check compares the reopened keydir against the in-memory oracle; exits 0 iff equal, 1 if different, 2 on setup error.crates/datawal-core/examples/gen_soak_fixtures.rs(~180 LOC). Deterministic SplitMix64-seeded JSONL generator. Three committed fixtures undertests/fixtures/soak/(small=100×512B, medium=100×3KiB, large=20×64KiB; ~2.2MB total). Same seeds reproduce the same bytes.docs/soak.md. Documents synthetic vs real, env vars, CSV columns, exit codes, what the soak is and is not.scripts/run_soak_real.sh. Refuses to run without explicitDATAWAL_SOAK_INPUT_{SMALL,MEDIUM,LARGE}pointing at readable files.What stays the same
WIRE_VERSION = 1. Corpus fixtures untouched.serde,serde_json,base64,anyhow.--examples.Env vars
DATAWAL_SOAK_DURATION1800(sec)DATAWAL_SOAK_ROTATE_EVERY5000DATAWAL_SOAK_COMPACT_EVERY_ROTATIONS4DATAWAL_SOAK_PROGRESS_SECS60DATAWAL_SOAK_LOG_DIR/tmpsoak.csvgoes.DATAWAL_SOAK_WORK_DIR${TMPDIR}/datawal-soakDATAWAL_SOAK_INPUT_{SMALL,MEDIUM,LARGE}--mode real.CSV columns:
elapsed_s,rss_kb,fds,segments,live_keys,puts,deletes,rotates,compacts,bytes_written.rss_kbandfdsare read from/proc/self/{status,fd}and are blank on non-Linux.Local validation
cargo fmt --all -- --check— cleancargo clippy --workspace --all-targets -- -D warnings— cleancargo test --workspace --all-targets— 124 tests greenRUSTDOCFLAGS='-D warnings' cargo doc --workspace --no-deps— cleancargo build --workspace --examples— cleanOut of scope (Tier 2)
dm-flakeyinjection