fix(memory): tick-path eviction spills collections instead of plain-dropping (task #45)#312
Conversation
… of plain-dropping them Root-causes the intermittent tests/cold_collection_visibility.rs CI flake (stable GHOST: EXISTS == 1 but LRANGE/ZRANGE/HGETALL/SMEMBERS permanently empty; reproduced on unmodified main, only on shared/slow Linux runners). Two compounding defects in storage::eviction::evict_one_with_spill (the synchronous spill path shared by the tick, the memory-pressure cascade's sync-spill fallback, and db_quota): 1. Collection victims (Hash/List/Set/ZSet/Stream) were gated behind a stale `is_string` check predating kv_spill::spill_to_datafile's full collection support (it already serializes any RedisValueRef via kv_serde) — a collection victim under a live SpillContext silently plain-dropped, indistinguishable from spill: None. 2. Even string victims never registered a ColdIndex entry after a successful sync spill (spill_to_datafile was always called with cold_index: None) — the durable .mpf file existed and was manifest- registered, but nothing could ever read it back. Separately, shard::timers::run_eviction (the periodic 100ms tick, independent of the memory-pressure cascade) never received a SpillContext at all — every victim it picked was plain-dropped even with --disk-offload enable and a durability backstop (--appendonly yes) configured. shard::persistence_tick::run_eviction_tick now builds a real SpillContext (ShardManifest + shard data dir + next_file_id) whenever disk-offload is enabled and a manifest is present, threading it through; falls back to the pre-existing fail-close plain-drop (PR #273 policy-aware discipline — noeviction still OOMs, an evicting policy still frees RAM) when no durability backstop exists, matching the documented "spill is inert without one" rule. Deterministic regression tests (no server process, no timing race): - storage::eviction::tests::sync_spill_non_string_victim_is_durably_spilled_not_plain_dropped - shard::timers::tests::test_run_eviction_spills_collection_victim_when_spill_context_given tests/cold_collection_visibility.rs is unmodified (its GHOST assertions are the correctness gate this fix satisfies) and green 10/10 locally on both runtimes (monoio release-fast + tokio jemalloc release-fast). Gates: cargo fmt --check clean; cargo clippy -- -D warnings clean (default + --no-default-features --features runtime-tokio,jemalloc); storage::eviction, shard::timers, shard::persistence_tick, storage::db_quota, storage::tiered lib test modules green. footer: closes task #45 author: Tin Dang
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughEviction now durably spills collection victims when a ChangesEviction spill behavior
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant run_eviction_tick
participant run_eviction
participant evict_one_with_spill
participant ColdIndex
run_eviction_tick->>run_eviction: pass SpillContext when configured
run_eviction->>evict_one_with_spill: forward SpillContext
evict_one_with_spill->>ColdIndex: register successful spill
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning Tools execution failed with the following error: Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error) Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
Task #45 — root cause of the recurring Linux-CI stable-GHOST flake (
cold_collection_visibility: EXISTS=1 but LRANGE/ZRANGE empty). Three compounding defects:evict_one_with_spill(src/storage/eviction.rs) gated spilling behind a staleis_stringcheck even thoughspill_to_datafilehad full collection support — collection victims under a live SpillContext were silently plain-dropped.ColdIndexentry — durable file existed but was unreachable.shard::timers::run_eviction) never received a SpillContext at all — every tick-evicted collection was plain-dropped even with disk-offload + appendonly enabled.persistence_tick.rsnow builds a real SpillContext from the shard manifest when disk-offload is enabled, fail-close otherwise (policy semantics unchanged).Verification
cold_collection_visibility: 10/10 green on monoio + tokio locally, 5/5 on Linux VM.Fixes the flake class that has been rerolled manually on multiple PRs (incl. #299/main runs 29189049422, 29186983648). Task #44 (
crash_recovery_disk_offload_no_aofpre-existing failure) may be affected — will recheck after merge.Refs: task #45, #41/#8 precedents.
Summary by CodeRabbit