use std::time::Duration;
use tokio::time::sleep;
#[derive(Clone)]
pub struct LatencyLayer {
rtt: Duration,
}
impl LatencyLayer {
pub fn new(rtt: Duration) -> Self {
Self { rtt }
}
}
impl<S> tower::Layer<S> for LatencyLayer {
type Service = LatencyService<S>;
fn layer(&self, service: S) -> Self::Service {
LatencyService {
inner: service,
rtt: self.rtt,
}
}
}
#[derive(Clone)]
pub struct LatencyService<S> {
inner: S,
rtt: Duration,
}
impl<S, Request> tower::Service<Request> for LatencyService<S>
where
S: tower::Service<Request> + Clone + Send + 'static,
S::Future: Send,
S::Response: Send,
S::Error: Send,
Request: Send + 'static,
{
type Response = S::Response;
type Error = S::Error;
type Future =
std::pin::Pin<Box<dyn std::future::Future<Output = Result<S::Response, S::Error>> + Send>>;
fn poll_ready(
&mut self,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, req: Request) -> Self::Future {
let clone = self.inner.clone();
let mut inner = std::mem::replace(&mut self.inner, clone);
let rtt = self.rtt;
Box::pin(async move {
let resp = inner.call(req).await;
if rtt != Duration::ZERO {
sleep(rtt).await;
}
resp
})
}
}