//! A peer connection service wrapper type to handle load tracking and provide access to the //! reported protocol version. 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, }; /// A client service wrapper that keeps track of its load. /// /// It also keeps track of the peer's reported protocol version. pub struct LoadTrackedClient { /// A service representing a connected peer, wrapped in a load tracker. service: PeakEwma, /// The metadata for the connected peer `service`. connection_info: Arc, } /// Create a new [`LoadTrackedClient`] wrapping the provided `client` service. impl From 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 { /// Retrieve the peer's reported protocol version. pub fn remote_version(&self) -> Version { self.connection_info.remote.version } } impl Service for LoadTrackedClient where Client: Service, { type Response = >::Response; type Error = >::Error; type Future = as Service>::Future; fn poll_ready(&mut self, context: &mut Context<'_>) -> Poll> { self.service.poll_ready(context) } fn call(&mut self, request: Request) -> Self::Future { self.service.call(request) } } impl Load for LoadTrackedClient { type Metric = as Load>::Metric; fn load(&self) -> Self::Metric { self.service.load() } }