Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] HttpMultiClient<T> Transport #1760

Open
0xrusowsky opened this issue Dec 6, 2024 · 0 comments
Open

[Feature] HttpMultiClient<T> Transport #1760

0xrusowsky opened this issue Dec 6, 2024 · 0 comments
Labels
enhancement New feature or request

Comments

@0xrusowsky
Copy link

0xrusowsky commented Dec 6, 2024

Component

rpc, transports

Describe the feature you would like

I’d like to propose a feature that could enhance the robustness of applications using alloy by implementing a built-in fallback mechanism for the http transport layer. This would help manage scenarios where the primary RPC provider is unavailable, improving reliability without requiring developers to implement custom in-app solutions or gateways.

I see 2 main benefits with such design:

  • "zero-cost" reliability: by automatically switching to a fallback provider, the app availability increases (while users simply need to inform an extra rpc url when initializing the provider).
  • better dev-ex: a built-in solution reduces development time for devs that would otherwise implement custom mechanisms + ensures consistency across apps.

Because of that i thought of implementing a new http transport to support multiple clients and potentially multiple request orchestration modes (although we could keep it simple and only use it as a fallback). Here the proposed impl:

pub struct HttpMultiClient<T> {
   primary: Http<T>,
   fallback: Http<T>,
   mode: MultiClientMode
}

pub enum MultiClientMode {
   Fallback,
   Fastest
}

impl<T> Service<RequestPacket> for HttpMultiClient<T> {
    type Response = ResponsePacket;
    type Error = TransportError;
    type Future = TransportFut<'static>;

    #[inline]
    fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> task::Poll<Result<(), Self::Error>> {
        task::Poll::Ready(Ok(()))
    }

    #[inline]
    fn call(&mut self, req: RequestPacket) -> Self::Future {
        match self.mode {
          MultiClientMode::Fallback => self.fallback_request(req) // todo
          MultiClientMode::Fastest => self.fastest_request(req)  // todo
       }
    }
}

then we could enhance the ProviderBuilder so that users would simply do something like:

//! Example of creating an HTTP provider using the `on_multi_http` method on the `ProviderBuilder`.

use alloy::providers::{Provider, ProviderBuilder};
use eyre::Result;

#[tokio::main]
async fn main() -> eyre::Result<()> {
    // Set up the HTTP transport which is consumed by the RPC client.
    let primary = "https://eth.merkle.io".parse()?;
    let fallback = "https://eth.llamarpc.com".parse()?;

    // Create a provider with the HTTP transport with fallback using the `reqwest` crate.
    let provider = ProviderBuilder::new().on_multi_http(primary, fallback, MultiClientMode::Fallback);

    Ok(())
}
  • do you think that this approach is sound?
  • do you foresee any potential challenges or limitations that i should consider?

I am eager to implement it myself if you guys think that it is a good idea, but design validation would be appreciated.
Thanks!

@0xrusowsky 0xrusowsky added the enhancement New feature or request label Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant