Skip to content

perf: RPC race mode — portfolio 1.2s (was 21–26s)#2

Merged
outputlayer merged 7 commits into
mainfrom
feat/rpc-race-mode
Apr 16, 2026
Merged

perf: RPC race mode — portfolio 1.2s (was 21–26s)#2
outputlayer merged 7 commits into
mainfrom
feat/rpc-race-mode

Conversation

@outputlayer
Copy link
Copy Markdown
Owner

Summary

  • Read-only Solana RPC calls now race across all configured endpoints in parallel. First successful response wins; losers are aborted mid-flight via JoinSet::abort_all. Writes (sendTransaction) and ordering-sensitive reads (getLatestBlockhash) stay sequential.
  • New RpcMode::{Sequential, Race} enum — every call-site explicitly picks a mode (compile-time safety against accidentally racing a write).
  • Per-URL timeout in race mode: 8s (was 20s sequential), since a slow node is almost always beaten by a fast peer.
  • rwa gm portfolio wall time: ~1.2–1.7s typical (previously 21–26s). rwa gm balance and other read-heavy commands benefit too.

Changes

  • crates/ondo/src/solana/rpc.rsRpcMode enum, single_attempt, rpc_call_race, single_batch_attempt, rpc_batch_race, OwnedRequest struct (+714 / -129 lines)
  • crates/ondo/src/solana/balance.rs — all read call-sites → RpcMode::Race; portfolio entry-point refactored for multi-URL support
  • crates/ondo/src/solana/{fee,transfer,transaction}.rs — read call-sites → Race; writes stay Sequential
  • crates/ondo/tests/rpc_portfolio.rs — new acceptance test: 2 mock servers (one 30s-stalled), asserts < 2s
  • 6 new unit tests for race failure modes (429 handling, error aggregation, single-URL fallback, non-retryable peer errors)

Test plan

  • 184 unit tests pass (cargo test -p rwa-ondo --lib)
  • 7 integration tests pass (cargo test -p rwa-ondo --features test-util --test rpc_portfolio)
  • cargo clippy --workspace --all-targets -- -D warnings clean
  • Smoke test: rwa gm portfolio returns in 1.04–1.54s across multiple runs
  • Race acceptance test asserts < 2s with stalled peer

🤖 Generated with Claude Code

outputlayer and others added 7 commits April 16, 2026 03:26
…or change)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extracts single_attempt (one URL, 3 retries w/ backoff) and adds rpc_call_race
that fans out to all URLs via JoinSet. First Ok wins, losers aborted.
8s per-URL timeout in race mode. Aggregated error when all nodes fail.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract single_batch_attempt (shared by sequential + race paths), add
rpc_batch_race with JoinSet fan-out and OwnedRequest for task ownership.
Batch race uses same 8s per-URL timeout as single-call race.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 429 on one peer + 200 on other → 200 wins
- both 5xx → aggregated error lists both URLs
- single URL list → race degenerates to single call
- non-retryable RPC error on peer + ok on other → ok wins

Also derive Debug on RpcResponse for test unwrap_err.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- balance.rs: getBalance, getTokenAccountsByOwner (USDC/Token-2022/specific),
  batch portfolio getMultipleAccounts → Race
- fee.rs: getRecentPrioritizationFees, getMinimumBalanceForRentExemption → Race
- transfer.rs: getAccountInfo, getTokenAccountsByOwner (both programs),
  chunked getMultipleAccounts → Race
- transaction.rs: getSignatureStatuses, simulateTransaction → Race;
  getLatestBlockhash + sendTransaction stay Sequential (ordering-sensitive / write)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds test-util Cargo feature exposing get_portfolio_balances_with_urls
(takes explicit URL slice instead of single --rpc-url). Refactors
get_portfolio_balances to delegate to a shared core function.

portfolio_race_beats_slow_url simulates the real failure: one mock stalls
response body 30s, the other responds fast. Run with:
  cargo test -p rwa-ondo --features test-util portfolio_race_beats_slow_url

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@outputlayer outputlayer merged commit 8165569 into main Apr 16, 2026
4 checks passed
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