use std::{sync::Arc, time::Duration};
use crate::config::{Cluster, UpstreamHttpVersion};
#[derive(Clone, Debug, Default)]
pub struct ConnectionOptions {
pub connection_timeout: Option<Duration>,
pub http_version: UpstreamHttpVersion,
pub idle_timeout: Option<Duration>,
pub read_timeout: Option<Duration>,
pub total_connection_timeout: Option<Duration>,
pub trusted_private_endpoints: Arc<[Box<str>]>,
pub write_timeout: Option<Duration>,
}
impl From<&Cluster> for ConnectionOptions {
fn from(cluster: &Cluster) -> Self {
Self {
connection_timeout: cluster.connection_timeout_ms.map(Duration::from_millis),
http_version: cluster.http.version,
idle_timeout: cluster.idle_timeout_ms.map(Duration::from_millis),
read_timeout: cluster.read_timeout_ms.map(Duration::from_millis),
total_connection_timeout: cluster.total_connection_timeout_ms.map(Duration::from_millis),
trusted_private_endpoints: cluster
.trusted_private_endpoints
.iter()
.map(|host| Box::from(super::strip_root_dot(host)))
.collect(),
write_timeout: cluster.write_timeout_ms.map(Duration::from_millis),
}
}
}
#[cfg(test)]
#[expect(clippy::allow_attributes, reason = "blanket test suppressions")]
#[allow(clippy::min_ident_chars, reason = "tests")]
mod tests {
use super::*;
#[test]
fn default_is_all_none() {
let opts = ConnectionOptions::default();
assert!(
opts.connection_timeout.is_none(),
"connection_timeout should default to None"
);
assert!(opts.idle_timeout.is_none(), "idle_timeout should default to None");
assert!(opts.read_timeout.is_none(), "read_timeout should default to None");
assert!(
opts.total_connection_timeout.is_none(),
"total_connection_timeout should default to None"
);
assert!(opts.write_timeout.is_none(), "write_timeout should default to None");
}
#[test]
fn from_cluster_maps_millis_to_duration() {
let c = cluster(Some(1000), Some(2000), Some(3000), Some(4000), Some(5000));
let opts = ConnectionOptions::from(&c);
assert_eq!(
opts.connection_timeout,
Some(Duration::from_millis(1000)),
"connection_timeout mismatch"
);
assert_eq!(
opts.idle_timeout,
Some(Duration::from_millis(2000)),
"idle_timeout mismatch"
);
assert_eq!(
opts.read_timeout,
Some(Duration::from_millis(3000)),
"read_timeout mismatch"
);
assert_eq!(
opts.total_connection_timeout,
Some(Duration::from_millis(5000)),
"total_connection_timeout mismatch"
);
assert_eq!(
opts.write_timeout,
Some(Duration::from_millis(4000)),
"write_timeout mismatch"
);
}
#[test]
fn from_cluster_preserves_none_fields() {
let c = cluster(Some(500), None, None, None, None);
let opts = ConnectionOptions::from(&c);
assert_eq!(
opts.connection_timeout,
Some(Duration::from_millis(500)),
"connection_timeout should be set"
);
assert!(opts.idle_timeout.is_none(), "idle_timeout should remain None");
assert!(opts.read_timeout.is_none(), "read_timeout should remain None");
assert!(
opts.total_connection_timeout.is_none(),
"total_connection_timeout should remain None"
);
assert!(opts.write_timeout.is_none(), "write_timeout should remain None");
}
#[test]
fn from_cluster_all_none() {
let c = cluster(None, None, None, None, None);
let opts = ConnectionOptions::from(&c);
assert!(opts.connection_timeout.is_none(), "connection_timeout should be None");
assert!(opts.idle_timeout.is_none(), "idle_timeout should be None");
assert!(opts.read_timeout.is_none(), "read_timeout should be None");
assert!(
opts.total_connection_timeout.is_none(),
"total_connection_timeout should be None"
);
assert!(opts.write_timeout.is_none(), "write_timeout should be None");
}
fn cluster(
connection_timeout_ms: Option<u64>,
idle_timeout_ms: Option<u64>,
read_timeout_ms: Option<u64>,
write_timeout_ms: Option<u64>,
total_connection_timeout_ms: Option<u64>,
) -> Cluster {
Cluster {
connection_timeout_ms,
idle_timeout_ms,
read_timeout_ms,
total_connection_timeout_ms,
write_timeout_ms,
..Cluster::with_defaults("test", vec![])
}
}
}