Skip to content

Rate-limit topo bootstrap repair heads - #5161

Open
pwojcikdev wants to merge 1 commit into
nanocurrency:developfrom
pwojcikdev:topo-repair-rate-limit
Open

Rate-limit topo bootstrap repair heads#5161
pwojcikdev wants to merge 1 commit into
nanocurrency:developfrom
pwojcikdev:topo-repair-rate-limit

Conversation

@pwojcikdev

Copy link
Copy Markdown
Contributor

Problem

With topo bootstrap enabled, a synced node ramps to 100% disk read time after a few minutes and stays there (observed on Windows + RocksDB).

Repair heads re-scan the already-discovered topo range indefinitely, and topo_scan::maybe_advance zeroes a head's timestamp whenever a page makes progress, so the head re-fires as soon as the reply lands. On a synced node every repair page "makes progress", so the cooldown never engages; when a band is exhausted the head is immediately re-armed on the same band. The only limits are the shared topo_rate_limit (500 req/s) and the 64-page pre-check queue, so the sweep runs as fast as the pre-check can read the ledger, i.e. it pegs the disk by construction.

If the ledger has no topo index (--populate_topo_index never run on an existing ledger), topo_strategy::precheck falls back to probing every entry by hash, which turns that sweep into ~1.6k random block reads per page with fill_cache = false.

Changes

  • Add bootstrap.topo_scan.repair_rate_limit (default 20 req/s, 0 = unlimited) and a dedicated nano::rate_limiter in topo_strategy. It is applied through head_gates.include_repair, so a throttled repair head never stalls the spearhead on the shared scan thread; the spearhead keeps its current pacing.
  • Repair heads no longer run at all when ledger.flags.topo_index is off. The spearhead still works there (its pages are bounded), but a perpetual sweep needs the sequential topology crawler to be sane.

Testing

bootstrap.*, bootstrap_topo_scan.*, bootstrap_topo_blocks.*, toml.* pass. Not reproduced locally; the fix follows from the code path above and should be verified on the affected Windows/RocksDB setup.

🤖 Generated with Claude Code

Repair heads re-scan the discovered range indefinitely and re-fire as soon
as a page makes progress, so on a synced node they sweep the whole ledger
at line rate, bounded only by the pre-check throughput. Without the topo
index the pre-check probes every entry by hash, turning the sweep into a
perpetual random-read storm that pegs the disk.

Add `topo_scan.repair_rate_limit` (20 req/s) with a dedicated limiter in
`topo_strategy`, applied via the repair gate so a throttled repair head
never stalls the spearhead. Repair heads are also disabled entirely when
the ledger has no topo index.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@gr0vity-dev-bot

gr0vity-dev-bot commented Sep 3, 2026

Copy link
Copy Markdown

Test Results for Commit b9a9811

Pull Request 5161: Results
Overall Status:

Test Case Results

  • 5n4pr_conf_10k_bintree: PASS (Duration: 115s)
  • 5n4pr_conf_10k_change: PASS (Duration: 145s)
  • 5n4pr_conf_change_dependant: PASS (Duration: 111s)
  • 5n4pr_conf_change_independant: PASS (Duration: 112s)
  • 5n4pr_conf_send_dependant: PASS (Duration: 120s)
  • 5n4pr_conf_send_independant: PASS (Duration: 120s)
  • 5n4pr_rocks_10k_bintree: PASS (Duration: 120s)
  • 5n4pr_rocks_10k_change: PASS (Duration: 247s)

Last updated: 2026-09-03 05:00:58 UTC

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