deboa_smol/client/http/conn/
pool.rs1use 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
14pub 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 pub fn set_max_idle_connections(&mut self, max_idle_connections: u32) {
49 self.max_idle_connections = max_idle_connections;
50 }
51
52 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}