use crate::circuit_breaker::CircuitBreakerConfig;
use crate::error_handling::ErrorThresholds;
use crate::rate_limiter::RateLimiterConfig;
use std::time::Duration;
#[derive(Clone, Debug, Default)]
pub struct ConnectionOptions {
pub base_url: Option<String>,
pub proxy: Option<String>,
pub api_key: Option<String>,
pub timeout: Option<Duration>,
pub disable_proxy: bool,
}
impl ConnectionOptions {
pub fn hydrate_with_env(mut self, provider_env_prefix: &str) -> Self {
if self.api_key.is_none() {
let specific = format!("{}_API_KEY", provider_env_prefix);
self.api_key = std::env::var(&specific)
.ok()
.or_else(|| std::env::var("AI_API_KEY").ok());
}
if self.base_url.is_none() {
if let Ok(v) = std::env::var("AI_BASE_URL") {
self.base_url = Some(v);
}
}
if self.proxy.is_none() && !self.disable_proxy {
self.proxy = std::env::var("AI_PROXY_URL").ok();
}
if self.timeout.is_none() {
if let Ok(v) = std::env::var("AI_TIMEOUT_SECS") {
if let Ok(secs) = v.parse::<u64>() {
self.timeout = Some(Duration::from_secs(secs));
}
}
}
self
}
}
#[derive(Debug, Clone, Default)]
pub struct ResilienceConfig {
pub circuit_breaker: Option<CircuitBreakerConfig>,
pub rate_limiter: Option<RateLimiterConfig>,
pub backpressure: Option<BackpressureConfig>,
pub error_handling: Option<ErrorHandlingConfig>,
}
#[derive(Debug, Clone)]
pub struct BackpressureConfig {
pub max_concurrent_requests: usize,
}
#[derive(Debug, Clone)]
pub struct ErrorHandlingConfig {
pub enable_recovery: bool,
pub enable_monitoring: bool,
pub error_thresholds: ErrorThresholds,
}
impl Default for BackpressureConfig {
fn default() -> Self {
Self {
max_concurrent_requests: 100,
}
}
}
impl Default for ErrorHandlingConfig {
fn default() -> Self {
Self {
enable_recovery: true,
enable_monitoring: true,
error_thresholds: ErrorThresholds::default(),
}
}
}
impl ResilienceConfig {
pub fn smart_defaults() -> Self {
Self {
circuit_breaker: Some(CircuitBreakerConfig::default()),
rate_limiter: Some(RateLimiterConfig::default()),
backpressure: Some(BackpressureConfig::default()),
error_handling: Some(ErrorHandlingConfig::default()),
}
}
pub fn production() -> Self {
Self {
circuit_breaker: Some(CircuitBreakerConfig::production()),
rate_limiter: Some(RateLimiterConfig::production()),
backpressure: Some(BackpressureConfig {
max_concurrent_requests: 50,
}),
error_handling: Some(ErrorHandlingConfig {
enable_recovery: true,
enable_monitoring: true,
error_thresholds: ErrorThresholds {
error_rate_threshold: 0.05, consecutive_errors: 3,
time_window: Duration::from_secs(30),
},
}),
}
}
pub fn development() -> Self {
Self {
circuit_breaker: Some(CircuitBreakerConfig::development()),
rate_limiter: Some(RateLimiterConfig::development()),
backpressure: Some(BackpressureConfig {
max_concurrent_requests: 200,
}),
error_handling: Some(ErrorHandlingConfig {
enable_recovery: false,
enable_monitoring: false,
error_thresholds: ErrorThresholds::default(),
}),
}
}
}