From 5787ad246be35be85de98dc3d499499e7ebdc2e4 Mon Sep 17 00:00:00 2001 From: Artem Goncharov Date: Thu, 9 Oct 2025 16:15:14 +0200 Subject: [PATCH] feat: Add connection pooling in openstack_sdk - add support for connection pooling and timeout - enable deflate, gzip and http2 features of reqwest --- Cargo.lock | 53 +++++++++++++++++++++++----- openstack_sdk/Cargo.toml | 3 +- openstack_sdk/src/openstack_async.rs | 15 +++++++- 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 227914d5d..be6b3b673 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -174,6 +174,19 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "async-compression" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d615619615a650c571269c00dca41db04b9210037fa76ed8239f70404ab56985" +dependencies = [ + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + [[package]] name = "async-lock" version = "3.4.1" @@ -599,6 +612,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -1034,6 +1056,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" +[[package]] +name = "flate2" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1269,19 +1301,13 @@ dependencies = [ "foldhash", ] -[[package]] -name = "hashbrown" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" - [[package]] name = "hashlink" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.15.5", + "hashbrown", ] [[package]] @@ -1622,7 +1648,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown 0.16.0", + "hashbrown", ] [[package]] @@ -1925,7 +1951,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.5", + "hashbrown", ] [[package]] @@ -2004,6 +2030,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -2793,11 +2820,13 @@ version = "0.12.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" dependencies = [ + "async-compression", "base64 0.22.1", "bytes", "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "http-body-util", @@ -3177,6 +3206,12 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "similar" version = "2.7.0" diff --git a/openstack_sdk/Cargo.toml b/openstack_sdk/Cargo.toml index 6e5d39e7c..fc36f72f2 100644 --- a/openstack_sdk/Cargo.toml +++ b/openstack_sdk/Cargo.toml @@ -65,7 +65,8 @@ json-patch = { workspace = true } lazy_static = { workspace = true } open.workspace = true regex = { workspace = true } -reqwest = { workspace = true } +reqwest = { workspace = true, features = ["gzip", "deflate", "http2", + "system-proxy"] } secrecy = { version = "0.10", features = ["serde"] } serde = { workspace = true } serde_json = {workspace = true} diff --git a/openstack_sdk/src/openstack_async.rs b/openstack_sdk/src/openstack_async.rs index aa7a46910..447808555 100644 --- a/openstack_sdk/src/openstack_async.rs +++ b/openstack_sdk/src/openstack_async.rs @@ -23,7 +23,7 @@ use http::{header, HeaderMap, HeaderValue, Response as HttpResponse, StatusCode} use reqwest::{Body, Certificate, Client as AsyncClient, Request, Response}; use std::convert::TryInto; use std::fmt::{self, Debug}; -use std::time::SystemTime; +use std::time::{Duration, SystemTime}; use std::{fs::File, io::Read}; use tokio_util::codec; use tokio_util::compat::FuturesAsyncReadCompatExt; @@ -193,6 +193,19 @@ impl AsyncOpenStack { ); client_builder = client_builder.danger_accept_invalid_certs(true); } + client_builder = client_builder.pool_max_idle_per_host(10); + client_builder = client_builder.pool_idle_timeout(Duration::from_secs(30)); + client_builder = client_builder.timeout(Duration::from_secs( + config + .options + .get("api_timeout") + .and_then(|val| val.clone().into_uint().ok()) + .unwrap_or(30), + )); + client_builder = client_builder.connect_timeout(Duration::from_secs(5)); + client_builder = client_builder.tcp_keepalive(Duration::from_secs(60)); + client_builder = client_builder.gzip(true); + client_builder = client_builder.deflate(true); let mut session = AsyncOpenStack { client: client_builder.build()?,