diff --git a/CHANGELOG.md b/CHANGELOG.md index 293586f..4962753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Changed -- Change pooling mechanism. +- Change pooling mechanism and add garbage collection of empty pools. - Update dependencies. ## 0.9.4 (2026-05-17) diff --git a/src/entrypoint.rs b/src/entrypoint.rs index b46c716..e80ef37 100644 --- a/src/entrypoint.rs +++ b/src/entrypoint.rs @@ -678,6 +678,17 @@ pub async fn entrypoint(config: ApplicationConfig) -> color_eyre::Result<()> { .log_format(log_format) .build(), ); + let proxy_data = Arc::clone(&aliasing_proxy_data); + tokio::spawn(async move { + let mut cleanup_interval = interval(Duration::from_secs(300)); + cleanup_interval.tick().await; + loop { + cleanup_interval.tick().await; + proxy_data + .keepalive_http11_pool_map + .retain(|_, pool| pool.status().available == 0); + } + }); let mut sandhole = Arc::new(SandholeServer { session_id: AtomicUsize::new(0), sessions_password: Mutex::default(), @@ -787,6 +798,17 @@ pub async fn entrypoint(config: ApplicationConfig) -> color_eyre::Result<()> { .log_format(log_format) .build(), ); + let proxy_data = Arc::clone(&http_proxy_data); + tokio::spawn(async move { + let mut cleanup_interval = interval(Duration::from_secs(300)); + cleanup_interval.tick().await; + loop { + cleanup_interval.tick().await; + proxy_data + .keepalive_http11_pool_map + .retain(|_, pool| pool.status().available == 0); + } + }); DroppableHandle(tokio::spawn(async move { loop { let proxy_data = Arc::clone(&http_proxy_data); @@ -870,6 +892,17 @@ pub async fn entrypoint(config: ApplicationConfig) -> color_eyre::Result<()> { .log_format(log_format) .build(), ); + let proxy_data = Arc::clone(&https_proxy_data); + tokio::spawn(async move { + let mut cleanup_interval = interval(Duration::from_secs(300)); + cleanup_interval.tick().await; + loop { + cleanup_interval.tick().await; + proxy_data + .keepalive_http11_pool_map + .retain(|_, pool| pool.status().available == 0); + } + }); let sandhole_clone = Arc::clone(&sandhole); let ssh_config_clone = Arc::clone(&ssh_config); DroppableHandle(tokio::spawn(async move { diff --git a/src/http/http11.rs b/src/http/http11.rs index f3da99a..4bc8d28 100644 --- a/src/http/http11.rs +++ b/src/http/http11.rs @@ -306,14 +306,6 @@ where // Create entry for pool let key_clone = key.clone(); let pool_size = proxy_data.http_pool_size; - let pool = { - let pool_ref = proxy_data - .keepalive_http11_pool_map - .entry(key_clone) - .or_insert_with(|| deadpool::unmanaged::Pool::new(pool_size)) - .downgrade(); - pool_ref.clone() - }; let response = match proxy_data.http_request_timeout { // Await for a response under the given duration. @@ -374,11 +366,14 @@ where proxy_data.log_format, ); // Return sender to pool - tokio::spawn(async move { - let pooled = PooledConnection::new(sender, tx); - let _ = pool.add(pooled).await; - drop(_guard); - }); + let pooled = PooledConnection::new(sender, tx); + let pool_ref = proxy_data + .keepalive_http11_pool_map + .entry(key_clone) + .or_insert_with(|| deadpool::unmanaged::Pool::new(pool_size)) + .downgrade(); + let _ = pool_ref.try_add(pooled); + drop(_guard); })), })); } diff --git a/src/http/http2.rs b/src/http/http2.rs index ac2e356..5964ea3 100644 --- a/src/http/http2.rs +++ b/src/http/http2.rs @@ -150,14 +150,6 @@ where // Create entry for pool let key_clone = key.clone(); let pool_size = proxy_data.http_pool_size; - let pool = { - let pool_ref = proxy_data - .keepalive_http2_pool_map - .entry(key_clone) - .or_insert_with(|| deadpool::unmanaged::Pool::new(pool_size)) - .downgrade(); - pool_ref.clone() - }; // Create an HTTP/2 handshake over the selected channel let mut uri_parts = request.uri().clone().into_parts(); @@ -231,11 +223,14 @@ where proxy_data.log_format, ); // Send sender to pool - tokio::spawn(async move { - let pooled = PooledConnection::new(sender, tx); - let _ = pool.add(pooled).await; - drop(_guard); - }); + let pooled = PooledConnection::new(sender, tx); + let pool_ref = proxy_data + .keepalive_http2_pool_map + .entry(key_clone) + .or_insert_with(|| deadpool::unmanaged::Pool::new(pool_size)) + .downgrade(); + let _ = pool_ref.try_add(pooled); + drop(_guard); })), })); } diff --git a/src/http/mod.rs b/src/http/mod.rs index cc714f7..43ab9ed 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -383,10 +383,12 @@ where { // Keep-alive pool for opened HTTP/1.1 connections. #[builder(default = Arc::default())] - keepalive_http11_pool_map: Arc, RandomState>>, + pub(crate) keepalive_http11_pool_map: + Arc, RandomState>>, // Keep-alive pool for opened HTTP/2 connections. #[builder(default = Arc::default())] - keepalive_http2_pool_map: Arc, RandomState>>, + pub(crate) keepalive_http2_pool_map: + Arc, RandomState>>, // Whether the server supports a queue pool for handlers. has_pool_queue: bool, // Maximum size for each connection pool.