Skip to content

fix(storage): truthful used_memory under disk-offload — RSS→logical ledger, stub-only recovery, replay demote (task #56)#349

Merged
pilotspacex-byte merged 2 commits into
mainfrom
fix/t56-used-memory-offload
Jul 16, 2026
Merged

fix(storage): truthful used_memory under disk-offload — RSS→logical ledger, stub-only recovery, replay demote (task #56)#349
pilotspacex-byte merged 2 commits into
mainfrom
fix/t56-used-memory-offload

Conversation

@pilotspacex-byte

@pilotspacex-byte pilotspacex-byte commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Task #56 (v0.8 item 2): make used_memory truthful under disk-offload. The G2 acceptance run reported 406–762MB against a 256MB cap, worse after kill-9 restart. Three independent bugs, diagnosed via an instrumented 2-shard/8MB/40k-key repro:

  1. used_memory was process RSS, not the logical ledger --maxmemory eviction gates on. It now reports the same kv(+ColdIndex)+vector+text+graph used-term the elastic budget gates on, plus Lua script cache and replication backlog for Redis parity; used_memory_rss/used_memory_peak unchanged; new moon_used_memory_bytes Prometheus gauge; MEMORY DOCTOR explains gated-vs-RSS-vs-outside-the-cap.
  2. Restart double-loaded spilled String keys hot (recovery.rs Phase 3): a pre-ColdIndex loop re-inserted every spilled String into the hot DashTable while the newer mechanism rebuilt the cold stub for the same key. All types now recover cold-stub-only with lazy promotion on first read.
  3. AOF replay re-heated cold keys (spilled keys get no AOF DEL, so replay reapplies their historical SETs hot — the "worse after restart" ~6× transient). Database::demote_replayed_cold_shadows reconciles post-replay, pre-serving.

Adversarial review trail (DO-NOT-SHIP → SHIP)

An independent adversarial review found and the fix round closed:

  • CRITICAL: overwrite-then-crash resurrected stale cold data (SET on a cold-shadowed key never cleared ColdIndex). Fixed crash-consistently: Database::set() clears the shadow on InsertOrUpdate::Updated; sound at replay because replay starts from an empty table — an Updated proves a later AOF record exists. Re-review verified coverage across SETRANGE/bit-ops/INCR/GETSET/collection-writes/RESTORE/COPY/Lua/MULTI.
  • HIGH: demote was inert under runtime-tokio + --shards 1 (no manifest branch); now wired in recover_shard_v3_pitr Phase 4b.
  • MEDIUM: parity gap (Lua cache + repl backlog) — included in the reported figure; eviction gate unchanged.

Verification

  • tests/used_memory_offload_truthful.rs (12 tests): spill → SIGKILL → restart; used_memory ≤ 1.75× maxmemory at steady state AND post-restart
  • tests/cold_shadow_overwrite_resurrection.rs: overwrite cold key → kill-9 → GET returns the NEW value (RED on pre-fix HEAD)
  • tests/cold_shadow_single_shard_tokio.rs: same, against a real tokio binary
  • All gates: fmt, clippy ×4 configs (default/tokio × lib/--tests), cargo test --lib 4332 passed, crash-matrix + cold-DEL regression suites green
  • Operator docs: docs/guides/monitoring.md — what counts against --maxmemory and what doesn't

Summary by CodeRabbit

  • Bug Fixes

    • Corrected used_memory reporting during disk offload to reflect logical memory usage rather than process RSS.
    • Prevented stale or duplicated cold data from returning after overwrites, AOF replay, or restart recovery.
    • Improved memory accounting to include Lua scripts and replication backlog.
    • Expanded MEMORY DOCTOR with clearer memory breakdowns.
  • Documentation

    • Added guidance distinguishing logical memory, eviction budget, and process RSS.
    • Updated monitoring examples for accurate memory alerts.
  • Tests

    • Added regression coverage for crash recovery, overwrites, replay, and memory reporting.

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@TinDang97, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ad7847ac-a4ce-4e80-9e75-aa3c71764141

📥 Commits

Reviewing files that changed from the base of the PR and between ae45e2f and fc56c7b.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • docs/guides/monitoring.md
  • src/admin/metrics_setup.rs
  • src/command/connection.rs
  • src/command/server_admin.rs
  • src/main.rs
  • src/persistence/recovery.rs
  • src/storage/db.rs
  • tests/cold_shadow_overwrite_resurrection.rs
  • tests/cold_shadow_single_shard_tokio.rs
  • tests/used_memory_offload_truthful.rs
📝 Walkthrough

Walkthrough

Disk-offload memory reporting now uses a logical ledger instead of RSS. Recovery invalidates stale cold shadows and demotes redundant replayed hot copies across replay paths. Monitoring documentation, changelog entries, unit tests, and ignored end-to-end crash-recovery tests cover the updated behavior.

Changes

Disk-offload correctness

Layer / File(s) Summary
Logical memory accounting
src/admin/metrics_setup.rs, src/command/connection.rs, src/command/server_admin.rs, docs/guides/monitoring.md
Adds logical used-memory accounting for storage, Lua cache, and replication backlog; exposes it through metrics, INFO, MEMORY DOCTOR, and monitoring guidance.
Cold-shadow invalidation and demotion
src/storage/db.rs
Clears stale cold-index entries after updates and demotes redundant hot replay copies while preserving cold read-through.
Replay recovery demotion
src/main.rs, src/persistence/recovery.rs
Runs cold-shadow reconciliation after multi-part AOF and legacy fallback replay paths.
Regression coverage and release documentation
tests/cold_shadow_*.rs, tests/used_memory_offload_truthful.rs, CHANGELOG.md
Adds unit and ignored integration coverage for overwrite resurrection, replay recovery, and bounded logical memory usage, and documents the fixes.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AOFReplay
  participant Recovery
  participant Database
  AOFReplay->>Recovery: complete replay
  Recovery->>Database: demote_replayed_cold_shadows()
  Database->>Database: remove redundant hot copies
  Database-->>Recovery: return demoted count
Loading

Possibly related PRs

Suggested reviewers: tindang97

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The summary is strong, but the required Checklist, Performance Impact, and Notes sections are missing. Add the missing template sections, including test status in Checklist, a Performance Impact note, and a Notes section.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main storage and disk-offload memory-reporting changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/t56-used-memory-offload

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@TinDang97
TinDang97 force-pushed the fix/t56-used-memory-offload branch from 4b9b003 to ae45e2f Compare July 16, 2026 04:03

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/persistence/recovery.rs (1)

703-726: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Iterate over all databases for consistency.

While disk offload currently targets databases[0], iterating over all databases matches the loop structure in main.rs and ensures future-proofing if disk offload is expanded to multiple databases.

♻️ Proposed refactor
-    if let Some(db0) = databases.first_mut() {
-        let demoted = db0.demote_replayed_cold_shadows();
-        if demoted > 0 {
-            info!(
-                "Shard {}: demoted {} AOF-replay hot shadow(s) back to cold-only \
-                 stubs (Phase 4b fallback path, used_memory truthful after restart, task `#56`)",
-                shard_id, demoted
-            );
-        }
-    }
+    let mut total_demoted = 0;
+    for db in databases.iter_mut() {
+        total_demoted += db.demote_replayed_cold_shadows();
+    }
+    if total_demoted > 0 {
+        info!(
+            "Shard {}: demoted {} AOF-replay hot shadow(s) back to cold-only \
+             stubs (Phase 4b fallback path, used_memory truthful after restart, task `#56`)",
+            shard_id, total_demoted
+        );
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/persistence/recovery.rs` around lines 703 - 726, Update the Phase 4b
fallback reconciliation to iterate over every database in databases instead of
only databases.first_mut(). Call demote_replayed_cold_shadows on each database
and log each positive demotion count with the corresponding shard context,
preserving the existing behavior and message for each database.
src/storage/db.rs (1)

1290-1345: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

File exceeds the 1500-line cap; this PR adds further to an already-oversized file.

demote_replayed_cold_shadows and its doc comment (plus the two new tests later in the file) are correct, but they land in a src/storage/db.rs that's already several times past the documented 1500-line limit. Consider splitting cold-tier-specific Database methods (promotion/demotion/cold accessors) and their tests into a dedicated submodule.

As per coding guidelines, "No single Rust file should exceed 1500 lines. Split command-group files into directory modules when approaching the limit; split read and write implementations above 1000 lines."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage/db.rs` around lines 1290 - 1345, Extract cold-tier-specific
Database methods, including demote_replayed_cold_shadows, promotion/demotion
logic, and cold accessors, into a dedicated storage submodule while preserving
their existing visibility and behavior. Move the associated cold-tier tests with
the implementation, and keep src/storage/db.rs under the 1500-line limit without
changing unrelated Database functionality.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/persistence/recovery.rs`:
- Around line 703-726: Update the Phase 4b fallback reconciliation to iterate
over every database in databases instead of only databases.first_mut(). Call
demote_replayed_cold_shadows on each database and log each positive demotion
count with the corresponding shard context, preserving the existing behavior and
message for each database.

In `@src/storage/db.rs`:
- Around line 1290-1345: Extract cold-tier-specific Database methods, including
demote_replayed_cold_shadows, promotion/demotion logic, and cold accessors, into
a dedicated storage submodule while preserving their existing visibility and
behavior. Move the associated cold-tier tests with the implementation, and keep
src/storage/db.rs under the 1500-line limit without changing unrelated Database
functionality.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f8d41d92-cccc-4b9a-8027-a9fcd757650c

📥 Commits

Reviewing files that changed from the base of the PR and between 8f5e0c9 and ae45e2f.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • docs/guides/monitoring.md
  • src/admin/metrics_setup.rs
  • src/command/connection.rs
  • src/command/server_admin.rs
  • src/main.rs
  • src/persistence/recovery.rs
  • src/storage/db.rs
  • tests/cold_shadow_overwrite_resurrection.rs
  • tests/cold_shadow_single_shard_tokio.rs
  • tests/used_memory_offload_truthful.rs

…task #56)

The G2 acceptance run (4 shards, --maxmemory 256MB, 2.6GB dataset,
disk-offload enabled) reported INFO used_memory at 406-762MB against the
256MB cap, and worse after a kill-9 restart. A 2-shard/8MB-cap/40k-key
macOS repro (tests/used_memory_offload_truthful.rs) instrumented at load,
steady state, and post-restart isolated three independent bugs:

1. used_memory was literally process RSS (src/command/connection.rs), not
   the logical ledger --maxmemory eviction actually gates on. RSS carries
   allocator overhead, mmap'd cold-read page-cache, the Lua script cache,
   and the replication backlog -- none of which eviction charges against
   the cap. INFO now reports the same KV(+ColdIndex)+vector+text+graph
   used-term ShardDatabases::recompute_elastic_budget already gates on
   (admin::metrics_setup::logical_used_memory_bytes); used_memory_rss /
   used_memory_peak still expose the true OS footprint, a new
   moon_used_memory_bytes Prometheus gauge mirrors the ledger, and MEMORY
   DOCTOR gained a "gated vs RSS vs outside-the-cap" section.

2. Restart double-loaded every spilled String key into hot RAM
   (src/persistence/recovery.rs): v3 recovery Phase 3 re-inserted each
   previously-spilled String entry directly into the hot DashTable
   (#79-04, predating cold read-through) AND rebuilt a ColdIndex stub for
   the same key (#80-02) -- nobody removed the first loop when the
   second, correct mechanism landed. Every value type now recovers as a
   cold-index-only stub; the first GET lazily promotes and only then
   charges used_memory, via the same path ordinary cold read-through uses.

3. AOF replay re-hydrated already-cold keys back into hot RAM on every
   restart (src/main.rs, src/storage/db.rs): fixing #2 exposed this
   second, independent path -- only surfaces with --appendonly yes AND
   disk-offload both active. An evicted-and-spilled key gets no AOF DEL
   record (record_reason_del never fires for a spilled entry), so AOF
   replay blindly reapplies the key's original SET into hot RAM with zero
   cold-tier awareness, transiently re-inflating used_memory to ~6x
   steady state after every restart (self-healing over several eviction
   ticks, slower the larger the offloaded dataset -- the "got WORSE after
   restart" symptom). Database::demote_replayed_cold_shadows reconciles
   this right after AOF replay finishes, before the server accepts
   connections: any key still present in the (already crash-consistent)
   ColdIndex at that point is provably redundant with what replay just
   wrote hot for it, so the redundant hot copy is dropped.

Red/green: tests/used_memory_offload_truthful.rs drives all three
mechanisms end-to-end (spill past maxmemory, confirm real disk spill,
SIGKILL, restart) and asserts used_memory stays within 1.75x maxmemory at
steady state AND immediately post-restart.

Before (pre-fix baseline binary): steady_max_used=39,632,896 (4.7x the
8MB cap; used == rss, confirming the RSS-as-used_memory bug) -- test
fails at the steady-state assertion.

After (all three fixes): steady_max_used=8,388,410 (~1.0x cap),
post_restart_max_used=8,388,410 (identical to steady state, no
post-restart transient at all) -- test passes both assertions,
reproducibly across repeated runs.

Scope: confined to accounting/reporting (charging, uncharging, INFO/
metrics surfaces, restart re-charge paths) per the task boundary --
spill file format/batching is owned by a separate concurrent effort and
was not touched.

Gates run on macOS (VM occupied by a concurrent crash-matrix run):
- cargo fmt --check: clean
- cargo clippy --tests -- -D warnings (default features): clean
- cargo clippy --no-default-features --features runtime-tokio,jemalloc --tests -- -D warnings: clean
- cargo test --lib (default features): 4331 passed, 0 failed, 1 ignored
- cargo test --lib --no-default-features --features runtime-tokio,jemalloc storage::db::: 35 passed
- cargo test --release --test used_memory_offload_truthful -- --ignored: pass (repeated)
- cargo test --release --test crash_matrix_per_shard_aof: 3 passed
- cargo test --release --test crash_recovery_cold_del_resurrection: 2 passed
- cargo test --release --test crash_recovery_disk_offload_no_aof: 1 passed
- cargo test --release --test crash_recovery_orphan_sweep_readiness: 1 passed
- cargo test --release --test memory_doctor_response: 1 passed
- cargo test --test aof_multidb_kill9: 4 passed

VM-scale validation still needed: re-run the original G2 acceptance
scenario (4 shards, 2.6GB dataset, --maxmemory 256MB) on moon-dev once
free, to confirm used_memory stays truthful at that scale and that the
post-restart AOF-replay-demotion pass completes promptly on a much
larger cold index / AOF incr log than this repro's 40k keys.

author: Tin Dang <tindang.ht97@gmail.com>
…_memory offload fix

Adversarial review of fix/t56-used-memory-offload flagged three gaps before
this branch could ship: a critical stale-data resurrection bug, a recovery
path where the new demotion logic was never invoked, and an undocumented
used_memory parity gap. All three are fixed here.

- CRITICAL: Database::set() (src/storage/db.rs) now clears a key's
  ColdIndex shadow the instant a second write to that key is observed
  (InsertOrUpdate::Updated). Without this, a key spilled at v1 and then
  live-overwritten to v2 (no re-eviction before a crash) would have its
  hot v2 wrongly dropped by demote_replayed_cold_shadows on restart,
  resurrecting stale v1. Provably safe because AOF replay always starts
  from an empty DashTable, so a key's first replayed write is always
  Inserted (left alone) and any later write during that replay can only
  be Updated if the AOF recorded a write after the one that got spilled.

- HIGH: recover_shard_v3_pitr's Phase 4b appendonly.aof fallback
  (src/persistence/recovery.rs) is the ONLY KV replay path under
  runtime-tokio + --shards 1 (no AofManifest exists there), and it never
  called demote_replayed_cold_shadows. It now does, closing the gap for
  that runtime/shard combination.

- MEDIUM: logical_used_memory_bytes() (src/admin/metrics_setup.rs) and
  the moon_used_memory_bytes gauge now include the Lua script cache and
  replication backlog, matching real Redis's used_memory semantics
  (allocator-attributed, not eviction-reclaimable). Both terms were
  already tracked as separate moon_memory_bytes{kind=...} gauges, so this
  costs no new instrumentation. The actual --maxmemory eviction gate
  (ShardDatabases::recompute_elastic_budget) is unchanged and narrower.
  MEMORY DOCTOR (src/command/server_admin.rs) and
  docs/guides/monitoring.md now show three distinct figures: elastic
  budget, used_memory (reported), and RSS.

New tests (all RED before their respective fix, GREEN after):
- storage::db::tests::test_second_write_invalidates_cold_shadow (unit)
- tests/cold_shadow_overwrite_resurrection.rs
  (overwritten_cold_key_returns_new_value_after_crash)
- tests/cold_shadow_single_shard_tokio.rs
  (single_shard_overwritten_cold_key_returns_new_value_after_crash, run
  against a runtime-tokio+jemalloc binary; uses SETEX per the
  monoio-write-gate/inline-SET dispatch gotcha)

Verified: cargo fmt --check, cargo clippy --tests -- -D warnings (default
features), cargo clippy --no-default-features --features
runtime-tokio,jemalloc --tests -- -D warnings, cargo test --lib (4332
passed), plus the full existing disk-offload/crash-recovery integration
suite (used_memory_offload_truthful, crash_recovery_cold_del_resurrection,
crash_matrix_per_shard_aof, memory_doctor_response, aof_multidb_kill9) —
all green with no regressions.

author: Tin Dang
@TinDang97
TinDang97 force-pushed the fix/t56-used-memory-offload branch from ae45e2f to fc56c7b Compare July 16, 2026 04:23
@pilotspacex-byte
pilotspacex-byte merged commit 0c57633 into main Jul 16, 2026
9 checks passed
@pilotspacex-byte
pilotspacex-byte deleted the fix/t56-used-memory-offload branch July 16, 2026 04:34
pilotspacex-byte added a commit that referenced this pull request Jul 16, 2026
…evidence (#356)

Re-ran the G2 acceptance benchmark (first run 2026-07-13 @ 983952a) on
main @ 4dcfd53 with the complete v0.8 storage batch merged (#347 t49
audit, #350 spill batching, #352 crash-matrix CI, #349 used_memory
truth, #353 vec-merge backoff). moon-dev VM, real-disk btrfs --dir,
appendonly=yes, 4 shards, 256MB cap, 260K x 10KB (2.6GB = 10x), runner
verified idle for all timed phases.

Results vs baseline:
- Spill files for the full 2.6GB: ~236,000 -> 840 (~280x, PR #350).
- used_memory: 406-762MB (RSS masquerading as the ledger) -> 1.00x cap
  at steady state; post-restart transient (AOF replay re-heats keys)
  drains to 255MB (< cap) within 5s and holds — demote pass logged
  "demoted 83,788 AOF-replay hot shadow(s)" (task #56, PR #349).
- Cold GET during active spill flood: worst 1,910ms -> 205ms (9.3x).
  Task #59 (per-shard read-vs-spill-writer fairness) remains open.
- kill-9 restart-to-PONG: 16.9s, decomposed as ~2s/shard cold-index
  rebuild (179K entries) + ~9.4s AOF incr replay (340K cmds / 3.3GB,
  no rewrite had fired). Criterion "readiness not O(spilled-keys)"
  holds — the cost is AOF-sized, the standard Redis-style bound; file
  count is out of the boot path.
- Integrity: 497/500 at first read (3 read-side artifacts during the
  post-replay drain), 500/500 on rediff after settle. Zero acked loss.

New finding filed as #355: DBSIZE counts only resident keys under
disk-offload (24,275 reported vs ~164K logical) — pre-existing
semantics gap, made visible by this investigation, non-blocking.

Also updates PRODUCTION-CONTRACT.md: CRASH-02 row (matrix 37->46 cells,
all green ungated, scheduled CI via PR #352), MEM-10X-01 row (this
re-run's evidence), and a 2026-07-16 audit-trail entry.

author: Tin Dang <tindang.ht97@gmail.com>

Co-authored-by: Tin Dang <tindang.ht97@gmail.com>
pilotspacex-byte added a commit that referenced this pull request Jul 16, 2026
…ne + 10× RAM datasets (#360)

Version 0.7.1 -> 0.8.0 (Cargo.toml + Cargo.lock), CHANGELOG [0.8.0] roll-up,
RELEASES.md ledger entry, ROADMAP v0.8.0 section flipped to SHIPPED (all 6
items ticked; exit-criterion wording corrected 42 -> 46 cells).

Release converts the storage kernel built during the v0.7.0 cycle into a
verifiable public claim:
- CRASH-02: 46-cell cross-plane kill-9 matrix green ungated, in scheduled CI
  (nightly full + Saturday ITERS=20 soak, PR #352)
- MEM-10X-01: G2 re-run on real disk (docs/perf/2026-07-16-g2-10x-ram-rerun.md,
  PR #356) — spill 236K -> 840 files (#350), used_memory 1.00x cap with <=5s
  post-restart drain (#349), cold-GET tail 1910 -> 205ms
- Plus: vector auto-merge CPU-livelock fix (#353), CI recall-canary
  offload (#354), task #49 audit-close (#347)

Disclosed follow-ups: task #59 read-vs-spill fairness (205ms tail, goal
<10ms), issue #355 DBSIZE resident-only under offload, restart time bounded
by AOF-rewrite cadence.

Tag gate: crash-matrix nightly full matrix + soak ITERS=20 both dispatched
on RC 82752af.

author: Tin Dang <tindang.ht97@gmail.com>

Co-authored-by: Tin Dang <tindang.ht97@gmail.com>
pilotspacex-byte pushed a commit to pilotspace/lunaris that referenced this pull request Jul 17, 2026
Pin vendor/moon at e41aa671 — the merge commit of pilotspace/moon
PR #351 on top of tag v0.8.0. This is deliberately AHEAD of the tag:
the tag alone lacks the DashTable double-NeedsSplit recovery-panic
fix (P0, deterministic on our production shard-0 checkpoint under
hash skew), which merged immediately after the release cut.

v0.8.0 "One Storage Kernel GA" highlights relevant to Lunaris:
- kill-9-lossless durability on every plane (KV/vector/FTS/graph/MQ),
  crash-matrix CI (#352)
- GraphUnion merge-recall abort-loop fixed via exponential backoff
  (#353) — the failure we observed live on 6381 since 2026-07-14
- truthful used_memory under disk-offload (#349), batched spill
  segments (#350), TLS pemfile -> pki-types

Validation (task moon-v080-bump, gates G1-G9):
- G7 upgrade-replay PASS: v0.7.1-written data dir replays intact on
  the v0.8.0 binary across all planes (KV/FT/graph/MQ/temporal)
- G8 dashtable A/B PASS: stock binary panics rc=101 on the
  reconstructed production checkpoint; v0.8.0+fix binary boots it in
  ~10s with dbsize 219,661 / 376 indexes / writes OK
- moondb SDK byte-identical (0.2.1); Cargo.lock moon 0.7.1 -> 0.8.0
- scripts/test-recovery.py gains LUNARIS_TEST_MOON_PORT override
  (OrbStack ai-proxy Redis wildcard-binds *:6380 and shadows the
  harness probe port)
- docs/durability.md §2.8 + book §3.5 record the GA wave and the
  pin-ahead-of-tag rationale

Live 6381 flip to this binary stays human-gated; until #353 is
verified draining the merge backlog, the
--max-unflushed-immutable-segments 4096 override stays in the
LaunchAgent plist.

refs: pilotspace/moon#349 #350 #351 #352 #353, task moon-v080-bump
author: Tin Dang
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants