1use std::time::Duration;
2use crate::circuit_breaker::CircuitBreakerConfig;
3use crate::rate_limiter::RateLimiterConfig;
4use crate::error_handling::ErrorThresholds;
5
6#[derive(Clone, Debug, Default)]
13pub struct ConnectionOptions {
14 pub base_url: Option<String>,
15 pub proxy: Option<String>,
16 pub api_key: Option<String>,
17 pub timeout: Option<Duration>,
18 pub disable_proxy: bool,
19}
20
21impl ConnectionOptions {
24 pub fn hydrate_with_env(mut self, provider_env_prefix: &str) -> Self {
29 if self.api_key.is_none() {
31 let specific = format!("{}_API_KEY", provider_env_prefix);
32 self.api_key = std::env::var(&specific)
33 .ok()
34 .or_else(|| std::env::var("AI_API_KEY").ok());
35 }
36 if self.base_url.is_none() {
38 if let Ok(v) = std::env::var("AI_BASE_URL") {
39 self.base_url = Some(v);
40 }
41 }
42 if self.proxy.is_none() && !self.disable_proxy {
44 self.proxy = std::env::var("AI_PROXY_URL").ok();
45 }
46 if self.timeout.is_none() {
48 if let Ok(v) = std::env::var("AI_TIMEOUT_SECS") {
49 if let Ok(secs) = v.parse::<u64>() {
50 self.timeout = Some(Duration::from_secs(secs));
51 }
52 }
53 }
54 self
55 }
56}
57
58#[derive(Debug, Clone, Default)]
60pub struct ResilienceConfig {
61 pub circuit_breaker: Option<CircuitBreakerConfig>,
62 pub rate_limiter: Option<RateLimiterConfig>,
63 pub backpressure: Option<BackpressureConfig>,
64 pub error_handling: Option<ErrorHandlingConfig>,
65}
66
67#[derive(Debug, Clone)]
69pub struct BackpressureConfig {
70 pub max_concurrent_requests: usize,
71}
72
73#[derive(Debug, Clone)]
75pub struct ErrorHandlingConfig {
76 pub enable_recovery: bool,
77 pub enable_monitoring: bool,
78 pub error_thresholds: ErrorThresholds,
79}
80
81impl Default for BackpressureConfig {
84 fn default() -> Self {
85 Self {
86 max_concurrent_requests: 100,
87 }
88 }
89}
90
91impl Default for ErrorHandlingConfig {
92 fn default() -> Self {
93 Self {
94 enable_recovery: true,
95 enable_monitoring: true,
96 error_thresholds: ErrorThresholds::default(),
97 }
98 }
99}
100
101impl ResilienceConfig {
102 pub fn smart_defaults() -> Self {
104 Self {
105 circuit_breaker: Some(CircuitBreakerConfig::default()),
106 rate_limiter: Some(RateLimiterConfig::default()),
107 backpressure: Some(BackpressureConfig::default()),
108 error_handling: Some(ErrorHandlingConfig::default()),
109 }
110 }
111
112 pub fn production() -> Self {
114 Self {
115 circuit_breaker: Some(CircuitBreakerConfig::production()),
116 rate_limiter: Some(RateLimiterConfig::production()),
117 backpressure: Some(BackpressureConfig {
118 max_concurrent_requests: 50,
119 }),
120 error_handling: Some(ErrorHandlingConfig {
121 enable_recovery: true,
122 enable_monitoring: true,
123 error_thresholds: ErrorThresholds {
124 error_rate_threshold: 0.05, consecutive_errors: 3,
126 time_window: Duration::from_secs(30),
127 },
128 }),
129 }
130 }
131
132 pub fn development() -> Self {
134 Self {
135 circuit_breaker: Some(CircuitBreakerConfig::development()),
136 rate_limiter: Some(RateLimiterConfig::development()),
137 backpressure: Some(BackpressureConfig {
138 max_concurrent_requests: 200,
139 }),
140 error_handling: Some(ErrorHandlingConfig {
141 enable_recovery: false,
142 enable_monitoring: false,
143 error_thresholds: ErrorThresholds::default(),
144 }),
145 }
146 }
147}