Feat: RPC failover support(read only) - #1073
Draft
tomatoishealthy wants to merge 2 commits into
Draft
tomatoishealthy wants to merge 2 commits into
tomatoishealthy wants to merge 2 commits into
Conversation
--l1.rpc now accepts a comma-separated endpoint list, primary first. Failover lives in an http.RoundTripper below the rpc layer, so every existing consumer keeps taking a plain *ethclient.Client and the rollup binding still receives a full bind.ContractBackend, including the SubscribeFilterLogs method that an HTTP-only client could not honestly implement. An endpoint is judged failed on a transport error, a 408/429/5xx status, or a reply that is not JSON. The last rule is not theoretical: on a network whose resolver answers for names that do not exist, a vanished endpoint returns HTTP 200 with an HTML block page. Judged on status alone that reads as success, and a devnet run showed the node keep using the dead endpoint until every L1 read failed upstream with "invalid character '<'", silently stopping block production with no error and no restart. Each attempt also carries GetBody so net/http can re-send a request whose pooled connection died. Without it that routine keep-alive race surfaces as an endpoint failure and the sticky switch demotes a healthy primary for the life of the process. A single endpoint keeps the previous ethclient.Dial behaviour, including ws:// and IPC, so existing configurations are unaffected. AI-Developer: claude-opus-4.8 AI-Agent: claude code AI-Reviewer: none Harness-Skill: none Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A round of review findings on node/rpcfailover, plus failback to the primary. Endpoint health. 401 and 403 now count as endpoint failures: endpoints carry their own credentials, so an expired key or an exhausted quota on one provider says nothing about the next, and hosted providers use exactly these statuses for it. 3xx counts too, because attempt() rewrites every request's URL: a redirect target would be discarded and the same endpoint asked again until http.Client gives up after ten hops, with no failover. 400 and 404 still pass through, since those describe the request rather than the endpoint. Credential redaction. Two paths leaked an API key held in the URL path or query, because net/http's stripPassword only masks userinfo. One is url.Parse's error, which formats as parse "<raw url>". The other is the bootstrap URL given to rpc.DialOptions, which is also the URL http.Client reports when it wraps a transport error; that URL is only a default target which attempt() always replaces, so redacting it costs nothing. Response body bound. A server that sends headers and then goes quiet had no bound at all: ResponseHeaderTimeout stops at the headers, the rpc layer sets no deadline, and the node's callers pass contexts derived from context.Background(). The caller blocked forever, and since L1Tracker calls the RPC inline from its tick loop and evaluates the halt gate inside that same loop, the gate stayed open -- the node would keep producing against an arbitrarily stale L1 view with nothing to report it. An inactivity deadline on the connection bounds this without capping legitimately large replies. HTTP/2 is disabled because that bound depends on it. The deadline lives on the connection, and under HTTP/2 one connection carries many concurrent streams whose traffic would keep pushing it forward. TLSNextProto alone is not enough: it stops net/http from handing the connection to its HTTP/2 implementation but not ALPN from negotiating h2, and a server that then selects h2 leaves the HTTP/1.x code reading frames as a response. Failback. A fallback is no longer permanent -- every failbackAfter, one call re-tries the primary, so a recovered primary is re-adopted instead of waiting for the fallback to fail in turn. No background goroutine and no probe traffic; the window is advanced by CompareAndSwap, so concurrent calls share one extra attempt per window rather than paying one each. Each attempt now carries GetBody, so net/http can re-send a request whose pooled connection died. Without it that routine keep-alive race surfaced as an endpoint failure and the sticky switch demoted a healthy primary for the life of the process. Known gaps are unchanged and documented in the package comment: a body that stalls after its first bytes is bounded but cannot be failed over, and a gateway reply that is JSON without being a JSON-RPC envelope is not detected. AI-Developer: claude-opus-4.8 AI-Agent: claude code AI-Reviewer: none Harness-Skill: none Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueWarning Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
No description provided.