use std::{
sync::Arc,
task::{Context, Poll},
};
use tower::{
load::{Load, PeakEwma},
Service,
};
use crate::{
constants::{EWMA_DECAY_TIME_NANOS, EWMA_DEFAULT_RTT},
peer::{Client, ConnectionInfo},
protocol::external::types::Version,
};
#[derive(Debug)]
pub struct LoadTrackedClient {
service: PeakEwma<Client>,
connection_info: Arc<ConnectionInfo>,
}
impl From<Client> for LoadTrackedClient {
fn from(client: Client) -> Self {
let connection_info = client.connection_info.clone();
let service = PeakEwma::new(
client,
EWMA_DEFAULT_RTT,
EWMA_DECAY_TIME_NANOS,
tower::load::CompleteOnResponse::default(),
);
LoadTrackedClient {
service,
connection_info,
}
}
}
impl LoadTrackedClient {
pub fn remote_version(&self) -> Version {
self.connection_info.remote.version
}
}
impl<Request> Service<Request> for LoadTrackedClient
where
Client: Service<Request>,
{
type Response = <Client as Service<Request>>::Response;
type Error = <Client as Service<Request>>::Error;
type Future = <PeakEwma<Client> as Service<Request>>::Future;
fn poll_ready(&mut self, context: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(context)
}
fn call(&mut self, request: Request) -> Self::Future {
self.service.call(request)
}
}
impl Load for LoadTrackedClient {
type Metric = <PeakEwma<Client> as Load>::Metric;
fn load(&self) -> Self::Metric {
self.service.load()
}
}