I have a gRPC service written in Rust using the tonic
crate. One of the methods of this service returns a stream (server-side grpc streaming) of values which are acquired by calling many devices on the network, which is why I need to rate-limit the stream. For this I'm using the governor
crate - mainly because it is already in the codebase I'm working on.
use governor::state::StreamRateLimitExt;
use governor::{Quota, RateLimiter};
#[tonic::async_trait]
impl ServiceTrait for MyService {
type ScanNetworkStream =
Pin<Box<dyn Stream<Item = Result<ScanNetworkResponse, tonic::Status>> + Send + 'static>>;
async fn scan_network(
&self,
_request: tonic::Request<()>,
) -> Result<tonic::Response<Self::ScanNetworkStream>, tonic::Status> {
// ...
let quota = Quota::per_second(per_second);
let limiter = RateLimiter::direct(quota);
let stream = futures::stream::iter(ips)
.ratelimit_stream(&limiter)
.map(move |ip: IpAddr| {
// some operations on IP
})
// some error handling, etc.
Ok(tonic::Response::new(Box::pin(stream)))
}
}
This code fails to compile with an error:
328 | ) -> Result<tonic::Response<Self::ScanNetworkStream>, tonic::Status> {
| --------------------------------------------------------------- type annotation requires that `limiter` is borrowed for `'static`
...
363 | .ratelimit_stream(&limiter)
| ^^^^^^^^ borrowed value does not live long enough
...
407 | }
| - `limiter` dropped here while still borrowed
Is there any way to keep the limiter alive?