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

Any plans to support jsonrpsee? #33

Open
jakerumbles opened this issue Jun 19, 2024 · 1 comment
Open

Any plans to support jsonrpsee? #33

jakerumbles opened this issue Jun 19, 2024 · 1 comment

Comments

@jakerumbles
Copy link

jakerumbles commented Jun 19, 2024

I've been trying to use this as tower middleware in a jsonrpsee server, and it works fine until I get to server.start() where the GovernorLayer has missing trait implementations. I thought it should work as it's supposed to be tower compatible, but maybe there is some specific jsonrpsee part of the equation here. For reference, I'm able to get the out-of-the-box Tower .rate_limit(3, Duration::from_secs(60)) middleware layer working just fine, but as soon as I try to use GovernorLayer instead it breaks due to missing trait implementations.

My code:

use anyhow::Result;
// use jsonrpsee::server::stop_channel;
use jsonrpsee::server::RpcModule;
// use jsonrpsee::server::RpcServiceBuilder;
use jsonrpsee::server::ServerHandle;
// use jsonrpsee::server::TowerService;
// use jsonrpsee::server::TowerServiceBuilder;
use jsonrpsee::server::{Server, ServerBuilder};
// use rate_limiting::{Rate, RateLimit};
use std::sync::Arc;
use std::time::Duration;
use tower::ServiceBuilder;
use tower_governor::{governor::GovernorConfigBuilder, GovernorLayer};

    pub async fn start(&self) -> Result<RpcServerHandle> {
        // Allow bursts with up to five requests per IP address
        // and replenishes one element every two seconds
        // We Box it because Axum 0.6 requires all Layers to be Clone
        // and thus we need a static reference to it
        let governor_conf = Arc::new(
            GovernorConfigBuilder::default()
                .per_second(2)
                .burst_size(5)
                .finish()
                .unwrap(),
        );

        let governor_limiter = governor_conf.limiter().clone();
        let interval = Duration::from_secs(60);
        // a separate background task to clean up
        std::thread::spawn(move || loop {
            std::thread::sleep(interval);
            tracing::info!("rate limiting storage size: {}", governor_limiter.len());
            governor_limiter.retain_recent();
        });

        // Add rate limiter middleware
        // let rpc_middleware = RpcServiceBuilder::new().layer_fn(
        //     |service: jsonrpsee::server::middleware::rpc::RpcService| {
        //         tracing::info!("MIDDLEWARE: RATE LIMITING");
        //         RateLimit::new(
        //             service,
        //             Rate {
        //                 num: 1,
        //                 period: Duration::from_secs(15),
        //             },
        //         )
        //     },
        // );

        let http_middleware = ServiceBuilder::new()
            // .rate_limit(3, Duration::from_secs(60));
            .layer(GovernorLayer {
                config: governor_conf,
            });

        // let (stop_handle, handle) = stop_channel();

        // let new_server = ServerBuilder::new()
        //     .set_http_middleware(http_middleware)
        //     // .to_service_builder()
        //     // .build(self.rpc_module.clone(), stop_handle);
        //     .build(self.settings.http_listen_addr())
        //     .await?;

        let server = Server::builder()
            // .set_rpc_middleware(middleware)
            .set_http_middleware(http_middleware)
            .build(self.settings.http_listen_addr())
            .await?;

        let addr = server.local_addr()?;
        tracing::info!("RPC server started at: {}", addr);

        let handle = server.start(self.rpc_module.clone());

        Ok(RpcServerHandle {
            listen_addr: addr,
            handle,
        })
    }

Here's the error on server.start()

the method `start` exists for struct `Server<Stack<GovernorLayer<PeerIpKeyExtractor, NoOpMiddleware<QuantaInstant>>, Identity>>`, but its trait bounds were not satisfied
the full type name has been written to '/Users/jake-dev/Github/drosera/crates/target/debug/deps/drosera_services-cbadea97acc5bca2.long-type-5025332530578171701.txt'
consider using `--verbose` to print the full type name to the console
the following trait bounds were not satisfied:
`<Governor<PeerIpKeyExtractor, governor::middleware::NoOpMiddleware<governor::clock::quanta::QuantaInstant>, jsonrpsee::jsonrpsee_server::server::TowerServiceNoHttp<tower::layer::util::Identity>> as Service<tonic::codegen::http::request::Request<tonic::transport::Body>>>::Response = tonic::codegen::http::response::Response<_>`
`<Governor<PeerIpKeyExtractor, governor::middleware::NoOpMiddleware<governor::clock::quanta::QuantaInstant>, jsonrpsee::jsonrpsee_server::server::TowerServiceNoHttp<tower::layer::util::Identity>> as Service<tonic::codegen::http::request::Request<tonic::transport::Body>>>::Error = std::boxed::Box<(dyn StdError + std::marker::Send + std::marker::Sync + 'static)>`
`Governor<PeerIpKeyExtractor, governor::middleware::NoOpMiddleware<governor::clock::quanta::QuantaInstant>, jsonrpsee::jsonrpsee_server::server::TowerServiceNoHttp<tower::layer::util::Identity>>: Service<tonic::codegen::http::request::Request<tonic::transport::Body>>`rustc[Click for full compiler diagnostic](rust-analyzer-diagnostics-view:/diagnostic%20message%20%5B2%5D?2#file%3A%2F%2F%2FUsers%2Fjake-dev%2FGithub%2Fdrosera%2Fcrates%2Fservices%2Fsrc%2Fnetwork%2Frpc%2Fmod.rs)
governor.rs(324, 1): doesn't satisfy `<_ as Service<Request<Body>>>::Error = Box<dyn Error + Send + Sync>`, `<_ as Service<Request<Body>>>::Response = Response<_>` or `_: Service<Request<Body>>`
@benwis
Copy link
Owner

benwis commented Oct 18, 2024

Since I mostly am only doing maintenance on this, I'd say no, but your'e welcome to take a look and see if any changes can be made to support this!

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

No branches or pull requests

2 participants