Skip to main content

deboa_smol/client/http/conn/
pool.rs

1use crate::{
2    cert::{DeboaCertificate, DeboaIdentity},
3    client::http::conn::{ConnectionConfig, ConnectionFactory, DeboaConnection},
4};
5use deboa::{
6    dns::DnsResolver,
7    errors::{ConnectionError, DeboaError},
8    Result,
9};
10use futures_timeout::TimeoutFutureExt;
11use hashbrown::HashMap;
12use std::time::Duration;
13
14/// Struct that represents the HTTP connection pool.
15///
16/// # Fields
17///
18/// * `connections` - The connections.
19pub struct HttpConnectionPool {
20    max_idle_connections: u32,
21    keep_alive_duration: Duration,
22    connections: HashMap<String, DeboaConnection>,
23}
24
25impl AsMut<HttpConnectionPool> for HttpConnectionPool {
26    fn as_mut(&mut self) -> &mut HttpConnectionPool {
27        self
28    }
29}
30
31impl Default for HttpConnectionPool {
32    fn default() -> Self {
33        Self {
34            max_idle_connections: 5,
35            keep_alive_duration: Duration::from_mins(5),
36            connections: HashMap::new(),
37        }
38    }
39}
40
41impl HttpConnectionPool {
42    /// Allow set max idle connections
43    ///
44    /// # Arguments
45    ///
46    /// * `max_idle_connections` - The max idle connections.
47    ///
48    pub fn set_max_idle_connections(&mut self, max_idle_connections: u32) {
49        self.max_idle_connections = max_idle_connections;
50    }
51
52    /// Allow set keep alive duration
53    ///
54    /// # Arguments
55    ///
56    /// * `keep_alive_duration` - The keep alive duration.
57    ///
58    pub fn set_keep_alive_duration(&mut self, keep_alive_duration: Duration) {
59        self.keep_alive_duration = keep_alive_duration;
60    }
61}
62
63impl deboa::conn::HttpConnectionPool for HttpConnectionPool {
64    type Identity = DeboaIdentity;
65    type Certificate = DeboaCertificate;
66    type ConnectionDispather = DeboaConnection;
67    type ConnectionCache = HashMap<String, DeboaConnection>;
68
69    fn new(max_idle_connections: u32, keep_alive_duration: Duration) -> Self {
70        Self { max_idle_connections, keep_alive_duration, connections: HashMap::new() }
71    }
72
73    #[inline]
74    fn connections(&self) -> &Self::ConnectionCache {
75        &self.connections
76    }
77
78    #[inline]
79    fn connection_count(&self) -> u32 {
80        self.connections
81            .len() as u32
82    }
83
84    async fn create_connection<'a, D>(
85        &mut self,
86        config: &ConnectionConfig<'a, Self::Identity, Self::Certificate>,
87        dns_resolver: &D,
88    ) -> Result<&mut DeboaConnection>
89    where
90        D: DnsResolver,
91    {
92        let host = config.host();
93        if self
94            .connections
95            .contains_key(host)
96        {
97            log::debug!("Connection already exists for {}, reusing.", host);
98            return Ok(self
99                .connections
100                .get_mut(host)
101                .unwrap());
102        }
103
104        log::debug!("Creating new connection for {}", host);
105        let connection = ConnectionFactory::create_connection(config, dns_resolver)
106            .timeout(config.connection_timeout())
107            .await
108            .map_err(|_| {
109                DeboaError::Connection(ConnectionError::Timeout {
110                    message: format!(
111                        "Connection to {} timed out after {:?}",
112                        host,
113                        config.connection_timeout()
114                    ),
115                })
116            })??;
117
118        self.connections
119            .insert(host.to_string(), connection);
120        Ok(self
121            .connections
122            .get_mut(host)
123            .unwrap())
124    }
125}