Skip to content

storage: cap RocksDB open table files and merge small ones (2026-10-28 archive crash loop) - #159

Merged
dendisuhubdy merged 1 commit into
mainfrom
fix/rocksdb-open-files
Oct 28, 2026
Merged

dendisuhubdy merged 1 commit into
mainfrom
fix/rocksdb-open-files

Conversation

@dendisuhubdy

Copy link
Copy Markdown
Member

Incident

2026-10-28 from ~10:21Z, archives e and obs1 crash-looped at RocksDB open (Too many open files, 355 / 291 restarts): ~67 000 table files vs the 65 536 soft limit. Consensus kept going (23/25), but randscan, the public RPC and the bridge observer froze. Mitigated on the hosts with LimitNOFILE=524288:524288; both back at head 11:32Z.

Cause

Default RocksDB options hold every table file open. WAL-full flushes write the quiet height-keyed families a few KB at a time, and with non-overlapping keys RocksDB only trivially moves those files down, never merges them. On e: anchors 22 084 files / 45 MB, perp_inputs 22 083 / 51 MB, blocks 17 542 / 22.5 GB. Each restart adds ~18 more. Pruned validators escape via compact_pruned_history; archives never prune.

Change

  • max_open_files = 16 384 (table cache).
  • Storage::tidy_small_files(budget): per family, in key order, chunks of ≤ 256 MiB holding ≥ 8 files averaging < 4 MiB are force-compacted to the bottom level; ≤ 1 GiB rewritten per pass (bounded temp disk — e has ~4.6 GB free).
  • Node runs it every 1 024 blocks via spawn_blocking, sharing the compacting flag with the history compaction.
  • CHANGELOG under unreleased v0.8.3.

Tests

New: the_store_caps_its_open_table_files, tidy_merges_a_family_of_tiny_files_and_keeps_every_row (200 files → ≤ 2, all rows intact), tidy_leaves_a_family_of_few_files_alone, tidy_stops_at_its_byte_budget, should_tidy_fires_every_tidy_interval_when_idle_and_shares_the_compaction_flag. Full cargo test -p randprotocol-node green (lib 808 passed); no clippy warnings in changed files.

Not measured: a tidy pass against a real archive store (first pass on e will drain the ~22 GB blocks backlog over ~20 passes ≈ 15 h).

🤖 Generated with Claude Code

2026-10-28: archives e and obs1 crash-looped at open (355 / 291 restarts) with
`Too many open files` once they held ~67 000 table files against the 65 536 soft
limit. WAL-full flushes write the quiet height-keyed families a few KB at a time
and RocksDB only moves such files down a level, never merges them (e: anchors
22 084 files / 45 MB, perp_inputs 22 083 / 51 MB, blocks 17 542 / 22.5 GB).
Pruned validators escape through compact_pruned_history; archives never prune.

- max_open_files = 16 384: a table cache instead of every file held open.
- Storage::tidy_small_files: per family, runs of >= 8 files averaging < 4 MiB,
  chunked at 256 MiB, force-compacted to the bottom level; 1 GiB per pass.
- The node runs it every 1 024 blocks off the loop, under the same one-at-a-time
  flag as the history compaction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dendisuhubdy
dendisuhubdy merged commit 97bcf4b into main Oct 28, 2026
22 checks passed
@dendisuhubdy
dendisuhubdy deleted the fix/rocksdb-open-files branch October 28, 2026 11:50
@codecov

codecov Bot commented Oct 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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.

1 participant