zebra_network/peer/
load_tracked_client.rs

1//! A peer connection service wrapper type to handle load tracking and provide access to the
2//! reported protocol version.
3
4use std::{
5    sync::Arc,
6    task::{Context, Poll},
7};
8
9use tower::{
10    load::{Load, PeakEwma},
11    Service,
12};
13
14use crate::{
15    constants::{EWMA_DECAY_TIME_NANOS, EWMA_DEFAULT_RTT},
16    peer::{Client, ConnectionInfo},
17    protocol::external::types::Version,
18};
19
20/// A client service wrapper that keeps track of its load.
21///
22/// It also keeps track of the peer's reported protocol version.
23#[derive(Debug)]
24pub struct LoadTrackedClient {
25    /// A service representing a connected peer, wrapped in a load tracker.
26    service: PeakEwma<Client>,
27
28    /// The metadata for the connected peer `service`.
29    connection_info: Arc<ConnectionInfo>,
30}
31
32/// Create a new [`LoadTrackedClient`] wrapping the provided `client` service.
33impl From<Client> for LoadTrackedClient {
34    fn from(client: Client) -> Self {
35        let connection_info = client.connection_info.clone();
36
37        let service = PeakEwma::new(
38            client,
39            EWMA_DEFAULT_RTT,
40            EWMA_DECAY_TIME_NANOS,
41            tower::load::CompleteOnResponse::default(),
42        );
43
44        LoadTrackedClient {
45            service,
46            connection_info,
47        }
48    }
49}
50
51impl LoadTrackedClient {
52    /// Retrieve the peer's reported protocol version.
53    pub fn remote_version(&self) -> Version {
54        self.connection_info.remote.version
55    }
56}
57
58impl<Request> Service<Request> for LoadTrackedClient
59where
60    Client: Service<Request>,
61{
62    type Response = <Client as Service<Request>>::Response;
63    type Error = <Client as Service<Request>>::Error;
64    type Future = <PeakEwma<Client> as Service<Request>>::Future;
65
66    fn poll_ready(&mut self, context: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
67        self.service.poll_ready(context)
68    }
69
70    fn call(&mut self, request: Request) -> Self::Future {
71        self.service.call(request)
72    }
73}
74
75impl Load for LoadTrackedClient {
76    type Metric = <PeakEwma<Client> as Load>::Metric;
77
78    fn load(&self) -> Self::Metric {
79        self.service.load()
80    }
81}