Skip to content

refactor(bootstrap): cap refresh concurrency #534

Merged
kariy merged 1 commit intomainfrom
refactor/bootstrap-refresh-concurrency
Apr 14, 2026
Merged

refactor(bootstrap): cap refresh concurrency #534
kariy merged 1 commit intomainfrom
refactor/bootstrap-refresh-concurrency

Conversation

@kariy
Copy link
Copy Markdown
Member

@kariy kariy commented Apr 14, 2026

Summary

  • Cap the Settings-change refresh at 8 concurrent in-flight probes via futures::StreamExt::buffer_unordered. Unbounded parallelism worked against local katana but trips rate limits on hosted Starknet RPC providers for larger manifests. 8 is high enough that the common case (2–10 items) finishes in one batch with no measurable overhead, low enough to stay under typical free-tier 20 req/s caps.
  • Delete TODOS.md. Both entries are resolved:
    • Bounded concurrency: addressed here.
    • Account-change refresh trigger: the original premise was wrong. The dirty flag already fires on any Settings field edit, not just RPC URL. compute_deploy_address already uses the current account, so unique=true deploys naturally re-probe at the new address when the signer changes. Locked down with tests.

Details

  • New REFRESH_CONCURRENCY: usize = 8 constant in tui.rs, with a const _: () = assert!(REFRESH_CONCURRENCY >= 1) compile-time guard (because buffer_unordered(0) would deadlock).
  • Probe futures boxed into Vec<Pin<Box<dyn Future<Output = ()> + Send>>> so declare and deploy probes share one stream. The async blocks have distinct anonymous types otherwise.
  • Three new unit tests:
    • settings_dirty_fires_on_account_edit_not_just_rpc — locks down that editing the Account field sets the dirty flag.
    • compute_deploy_address_uses_current_account_for_unique_deploys — confirms unique=true yields different addresses per caller, unique=false is caller-independent. This is the coupling that makes account-change refresh correct-by-construction.
    • needs_refresh_includes_done_and_unknown_but_not_pending_or_failed (pre-existing, unchanged).

Test plan

  • cargo nextest run -p katana-bootstrap — 98 passed, 0 failed
  • cargo clippy -p katana-bootstrap --all-targets --no-deps — only pre-existing warnings remain
  • cargo +nightly-2025-02-20 fmt --all
  • Manual sanity: queue a 10+ item manifest, execute, switch RPC. Confirm the Refreshing state completes in one batch and items resolve correctly.

🤖 Generated with Claude Code

Cap the Settings-change refresh at 8 concurrent in-flight probes via
`buffer_unordered`. Unbounded parallelism worked fine against local
katana but would trip rate limits on hosted Starknet RPC providers
for manifests above ~20 items. 8 is high enough that the common case
(2–10 items) finishes in one batch with no measurable overhead, low
enough to stay under typical free-tier 20 req/s caps.

A compile-time assertion guards against a future refactor setting
the constant to 0 (which would deadlock the refresh task, since
`buffer_unordered(0)` never advances).

Also retire both entries in TODOS.md:

- Bounded concurrency: addressed here.
- Account-change refresh trigger: the premise was wrong. The dirty
  flag fires on any Settings field edit, not just RPC URL, and
  `compute_deploy_address` already uses the current account — so
  unique=true deploys naturally re-probe at the new address when the
  user changes signer. Locked down with tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Benchmark

Details
Benchmark suite Current: a1b558d Previous: 3db9b65 Ratio
CompiledClass(fixture)/compress 2759042 ns/iter (± 15607) 2574151 ns/iter (± 8127) 1.07
CompiledClass(fixture)/decompress 2873840 ns/iter (± 13908) 2840607 ns/iter (± 12378) 1.01
ExecutionCheckpoint/compress 32 ns/iter (± 7) 35 ns/iter (± 4) 0.91
ExecutionCheckpoint/decompress 25 ns/iter (± 7) 27 ns/iter (± 9) 0.93
PruningCheckpoint/compress 32 ns/iter (± 8) 35 ns/iter (± 2) 0.91
PruningCheckpoint/decompress 25 ns/iter (± 5) 27 ns/iter (± 5) 0.93
VersionedHeader/compress 646 ns/iter (± 5) 658 ns/iter (± 10) 0.98
VersionedHeader/decompress 815 ns/iter (± 6) 866 ns/iter (± 17) 0.94
StoredBlockBodyIndices/compress 78 ns/iter (± 5) 81 ns/iter (± 1) 0.96
StoredBlockBodyIndices/decompress 36 ns/iter (± 9) 40 ns/iter (± 8) 0.90
StorageEntry/compress 145 ns/iter (± 2) 183 ns/iter (± 2) 0.79
StorageEntry/decompress 145 ns/iter (± 5) 155 ns/iter (± 6) 0.94
ContractNonceChange/compress 146 ns/iter (± 3) 184 ns/iter (± 7) 0.79
ContractNonceChange/decompress 241 ns/iter (± 4) 261 ns/iter (± 5) 0.92
ContractClassChange/compress 216 ns/iter (± 3) 217 ns/iter (± 4) 1.00
ContractClassChange/decompress 250 ns/iter (± 4) 281 ns/iter (± 5) 0.89
ContractStorageEntry/compress 162 ns/iter (± 3) 170 ns/iter (± 2) 0.95
ContractStorageEntry/decompress 311 ns/iter (± 8) 347 ns/iter (± 6) 0.90
GenericContractInfo/compress 136 ns/iter (± 5) 139 ns/iter (± 3) 0.98
GenericContractInfo/decompress 106 ns/iter (± 9) 111 ns/iter (± 4) 0.95
Felt/compress 82 ns/iter (± 3) 91 ns/iter (± 12) 0.90
Felt/decompress 69 ns/iter (± 7) 64 ns/iter (± 10) 1.08
BlockHash/compress 81 ns/iter (± 3) 91 ns/iter (± 18) 0.89
BlockHash/decompress 58 ns/iter (± 5) 61 ns/iter (± 13) 0.95
TxHash/compress 82 ns/iter (± 3) 91 ns/iter (± 3) 0.90
TxHash/decompress 58 ns/iter (± 7) 61 ns/iter (± 6) 0.95
ClassHash/compress 82 ns/iter (± 7) 90 ns/iter (± 11) 0.91
ClassHash/decompress 61 ns/iter (± 5) 61 ns/iter (± 7) 1
CompiledClassHash/compress 81 ns/iter (± 5) 90 ns/iter (± 4) 0.90
CompiledClassHash/decompress 58 ns/iter (± 7) 61 ns/iter (± 4) 0.95
BlockNumber/compress 47 ns/iter (± 3) 51 ns/iter (± 3) 0.92
BlockNumber/decompress 25 ns/iter (± 4) 26 ns/iter (± 1) 0.96
TxNumber/compress 47 ns/iter (± 2) 51 ns/iter (± 2) 0.92
TxNumber/decompress 26 ns/iter (± 0) 26 ns/iter (± 1) 1
FinalityStatus/compress 1 ns/iter (± 0) 0 ns/iter (± 0) +∞
FinalityStatus/decompress 12 ns/iter (± 2) 13 ns/iter (± 0) 0.92
TypedTransactionExecutionInfo/compress 16247 ns/iter (± 90) 14845 ns/iter (± 45) 1.09
TypedTransactionExecutionInfo/decompress 3612 ns/iter (± 107) 3709 ns/iter (± 70) 0.97
VersionedContractClass/compress 367 ns/iter (± 5) 362 ns/iter (± 6) 1.01
VersionedContractClass/decompress 766 ns/iter (± 20) 814 ns/iter (± 3) 0.94
MigratedCompiledClassHash/compress 159 ns/iter (± 5) 179 ns/iter (± 4) 0.89
MigratedCompiledClassHash/decompress 147 ns/iter (± 4) 162 ns/iter (± 9) 0.91
ContractInfoChangeList/compress 1515 ns/iter (± 45) 1524 ns/iter (± 78) 0.99
ContractInfoChangeList/decompress 2254 ns/iter (± 381) 2395 ns/iter (± 422) 0.94
BlockChangeList/compress 667 ns/iter (± 36) 653 ns/iter (± 101) 1.02
BlockChangeList/decompress 902 ns/iter (± 155) 980 ns/iter (± 164) 0.92
ReceiptEnvelope/compress 30908 ns/iter (± 1922) 28030 ns/iter (± 1145) 1.10
ReceiptEnvelope/decompress 6143 ns/iter (± 240) 6431 ns/iter (± 268) 0.96
TrieDatabaseValue/compress 165 ns/iter (± 2) 159 ns/iter (± 2) 1.04
TrieDatabaseValue/decompress 226 ns/iter (± 4) 242 ns/iter (± 4) 0.93
TrieHistoryEntry/compress 289 ns/iter (± 2) 292 ns/iter (± 2) 0.99
TrieHistoryEntry/decompress 262 ns/iter (± 11) 280 ns/iter (± 12) 0.94

This comment was automatically generated by workflow using github-action-benchmark.

Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.30.

Benchmark suite Current: a1b558d Previous: 3db9b65 Ratio
FinalityStatus/compress 1 ns/iter (± 0) 0 ns/iter (± 0) +∞

This comment was automatically generated by workflow using github-action-benchmark.

CC: @kariy

@github-actions
Copy link
Copy Markdown

Runner: AMD EPYC 7763 64-Core Processor (4 cores) · 15Gi RAM

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 14, 2026

Codecov Report

❌ Patch coverage is 78.94737% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.68%. Comparing base (9bde0ae) to head (a1b558d).
⚠️ Report is 367 commits behind head on main.

Files with missing lines Patch % Lines
crates/bootstrap/src/tui.rs 78.94% 8 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #534      +/-   ##
==========================================
- Coverage   73.32%   66.68%   -6.64%     
==========================================
  Files         209      308      +99     
  Lines       23132    42486   +19354     
==========================================
+ Hits        16961    28333   +11372     
- Misses       6171    14153    +7982     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@kariy kariy changed the title refactor(bootstrap): cap refresh concurrency and retire TODOs refactor(bootstrap): cap refresh concurrency Apr 14, 2026
@kariy kariy merged commit ae1d2ee into main Apr 14, 2026
15 of 17 checks passed
@kariy kariy deleted the refactor/bootstrap-refresh-concurrency branch April 14, 2026 22:13
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