use core::time::Duration;
use former::Former;
use crate::error::Error;
use super::Client;
#[ allow( clippy::struct_excessive_bools ) ]
#[ derive( Debug, Clone, Former ) ]
pub struct ClientConfig
{
pub api_key : String,
#[ former( default = "https://generativelanguage.googleapis.com".to_string() ) ]
pub base_url : String,
#[ former( default = Duration::from_secs( 30 ) ) ]
pub timeout : Duration,
#[ cfg( feature = "retry" ) ]
#[ former( default = 3_u32 ) ]
pub max_retries : u32,
#[ cfg( feature = "retry" ) ]
#[ former( default = Duration::from_millis( 100 ) ) ]
pub base_delay : Duration,
#[ cfg( feature = "retry" ) ]
#[ former( default = Duration::from_secs( 10 ) ) ]
pub max_delay : Duration,
#[ cfg( feature = "retry" ) ]
#[ former( default = true ) ]
pub enable_jitter : bool,
#[ cfg( feature = "retry" ) ]
#[ former( default = 2.0 ) ]
pub backoff_multiplier : f64,
#[ cfg( feature = "retry" ) ]
#[ former( default = false ) ]
pub enable_retry_metrics : bool,
#[ cfg( feature = "retry" ) ]
pub max_elapsed_time : Option< Duration >,
#[ cfg( feature = "circuit_breaker" ) ]
#[ former( default = false ) ]
pub enable_circuit_breaker : bool,
#[ cfg( feature = "circuit_breaker" ) ]
#[ former( default = 5_u32 ) ]
pub circuit_breaker_failure_threshold : u32,
#[ cfg( feature = "circuit_breaker" ) ]
#[ former( default = 3_u32 ) ]
pub circuit_breaker_success_threshold : u32,
#[ cfg( feature = "circuit_breaker" ) ]
#[ former( default = Duration::from_secs( 60 ) ) ]
pub circuit_breaker_timeout : Duration,
#[ cfg( feature = "caching" ) ]
#[ former( default = false ) ]
pub enable_request_cache : bool,
#[ cfg( feature = "caching" ) ]
#[ former( default = Duration::from_secs( 300 ) ) ]
pub cache_ttl : Duration,
#[ cfg( feature = "caching" ) ]
#[ former( default = 1000_usize ) ]
pub cache_max_size : usize,
#[ cfg( feature = "rate_limiting" ) ]
#[ former( default = false ) ]
pub enable_rate_limiting : bool,
#[ cfg( feature = "rate_limiting" ) ]
#[ former( default = 10.0 ) ]
pub rate_limit_requests_per_second : f64,
#[ cfg( feature = "rate_limiting" ) ]
#[ former( default = "token_bucket".to_string() ) ]
pub rate_limit_algorithm : String,
#[ cfg( feature = "rate_limiting" ) ]
#[ former( default = 100_usize ) ]
pub rate_limit_bucket_size : usize,
}
impl ClientConfig
{
#[ inline ]
pub fn build( &self ) -> Result< Client, Error >
{
if self.api_key.is_empty()
{
return Err( Error::AuthenticationError( "API key cannot be empty".to_string() ) );
}
#[ cfg( feature = "retry" ) ]
{
if self.backoff_multiplier <= 1.0
{
return Err( Error::InvalidArgument(
format!( "Backoff multiplier must be greater than 1.0, got : {0}", self.backoff_multiplier )
) );
}
if self.base_delay >= self.max_delay
{
return Err( Error::InvalidArgument(
"Base delay must be less than max delay".to_string()
) );
}
}
let http = reqwest::Client::builder()
.timeout( self.timeout )
.build()
.map_err( | e | Error::NetworkError( format!( "Failed to create HTTP client : {e}" ) ) )?;
#[ cfg( feature = "caching" ) ]
let request_cache = if self.enable_request_cache
{
let cache_config = crate::internal::http::CacheConfig {
max_size : self.cache_max_size,
ttl : self.cache_ttl,
enable_metrics : false, };
Some( std::sync::Arc::new( crate::internal::http::RequestCache::new( cache_config ) ) )
} else {
None
};
Ok( Client
{
api_key : self.api_key.clone(),
base_url : self.base_url.clone(),
http,
timeout : self.timeout,
#[ cfg( feature = "retry" ) ]
max_retries : self.max_retries,
#[ cfg( feature = "retry" ) ]
base_delay : self.base_delay,
#[ cfg( feature = "retry" ) ]
max_delay : self.max_delay,
#[ cfg( feature = "retry" ) ]
enable_jitter : self.enable_jitter,
#[ cfg( feature = "retry" ) ]
request_timeout : None, #[ cfg( feature = "retry" ) ]
backoff_multiplier : self.backoff_multiplier,
#[ cfg( feature = "retry" ) ]
enable_retry_metrics : self.enable_retry_metrics,
#[ cfg( feature = "retry" ) ]
max_elapsed_time : self.max_elapsed_time,
#[ cfg( feature = "circuit_breaker" ) ]
enable_circuit_breaker : self.enable_circuit_breaker,
#[ cfg( feature = "circuit_breaker" ) ]
circuit_breaker_failure_threshold : self.circuit_breaker_failure_threshold,
#[ cfg( feature = "circuit_breaker" ) ]
circuit_breaker_success_threshold : self.circuit_breaker_success_threshold,
#[ cfg( feature = "circuit_breaker" ) ]
circuit_breaker_timeout : self.circuit_breaker_timeout,
#[ cfg( feature = "circuit_breaker" ) ]
enable_circuit_breaker_metrics : false, #[ cfg( feature = "circuit_breaker" ) ]
circuit_breaker_shared_state : false, #[ cfg( feature = "caching" ) ]
enable_request_cache : self.enable_request_cache,
#[ cfg( feature = "caching" ) ]
cache_ttl : self.cache_ttl,
#[ cfg( feature = "caching" ) ]
cache_max_size : self.cache_max_size,
#[ cfg( feature = "caching" ) ]
enable_cache_metrics : false, #[ cfg( feature = "caching" ) ]
request_cache,
#[ cfg( feature = "rate_limiting" ) ]
enable_rate_limiting : self.enable_rate_limiting,
#[ cfg( feature = "rate_limiting" ) ]
rate_limit_requests_per_second : self.rate_limit_requests_per_second,
#[ cfg( feature = "rate_limiting" ) ]
rate_limit_algorithm : self.rate_limit_algorithm.clone(),
#[ cfg( feature = "rate_limiting" ) ]
rate_limit_bucket_size : self.rate_limit_bucket_size,
#[ cfg( feature = "rate_limiting" ) ]
enable_rate_limiting_metrics : false, #[ cfg( feature = "compression" ) ]
compression_config : None, } )
}
}
#[ derive( Debug ) ]
pub struct ConfigWatchHandle
{
pub( super ) _handle : std::sync::Arc< () >,
}