feat: add an HTTP connect timeout so unreachable RPC hosts fail fast - #172
Open
flyq wants to merge 1 commit into
Open
feat: add an HTTP connect timeout so unreachable RPC hosts fail fast#172flyq wants to merge 1 commit into
flyq wants to merge 1 commit into
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude review status
🛠️ Review did not finish Attempted head This round did not publish: MODEL_ACTION_FAILED in phase review_retry. Anything listed below is from the last round that did. Re-run the workflow or push a new commit to try again. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
RpcClientnow builds one shared reqwest client with a connect-phase bound (RpcClientConfig::connect_timeout, default 3s) and injects it into every alloy provider (data, witness, report). An endpoint whose TCP handshake gets no reply — a dead host, or a firewall silently dropping SYNs — now fails and rotates within ~3s instead of consuming the full 20sper_attempt_timeouton every attempt.Motivation
Observed on a mainnet debug-trace-server deploy: the internal witness generator endpoint sat behind a firewall that silently dropped SYNs, and every chain-sync block burned the whole 20s per-attempt budget on provider 0 before rotating to the working fallback (which then answered in ~60ms), capping sync throughput at ~0.1 blocks/s. Connection refusal (RST) already fails in milliseconds; only the no-reply case had no bound tighter than
per_attempt_timeout— and that one cannot simply be lowered without also cutting the budget for legitimately slow multi-MB witness transfers. The two failure modes need separate knobs.Change
RpcClientConfig::connect_timeoutfield (default 3s, enough for a WAN handshake that loses its first SYN) wired through a single sharedreqwest::Client(crates/stateless-common/src/rpc_client.rs:299); connection pools are keyed per host, so sharing one client across providers is behavior-neutral.alloy_rpc_client::ClientBuilder::http_with_client+RootProvider::newinstead ofProviderBuilder::connect_http; the alloy builder path preserves theis_localguessing of the previous shape.alloy-rpc-client(same 1.0.23 family as the existing alloy deps,default-features = false; itsreqwestfeature is already enabled through alloy-provider via feature unification).Cargo.lockgains only the new dependency edge.Testing
New
test_connect_timeout_rotates_past_unreachable_provider: a backlog-1 listener with a pre-filled accept queue models the SYN-drop case; withconnect_timeout=200msandper_attempt_timeout=60s,get_latest_block_numberrotates to the healthy second endpoint well inside a 5s outer bound (the test self-skips if the host kernel refuses to saturate the queue). Negative check performed locally: lifting the connect bound to 50s makes the test fail via the outer timeout, so the simulation genuinely hangs the connect phase rather than getting an RST.cargo test -p stateless-common: 41 passed; fmt/clippy/cargo-sort clean.🤖 Generated with Claude Code