1use std::time::Duration;
2use crate::circuit_breaker::CircuitBreakerConfig;
3use crate::rate_limiter::RateLimiterConfig;
4use crate::error_handling::ErrorThresholds;
5
6#[derive(Clone, Debug)]
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 Default for ConnectionOptions {
22 fn default() -> Self {
23 Self {
24 base_url: None,
25 proxy: None,
26 api_key: None,
27 timeout: None,
28 disable_proxy: false,
29 }
30 }
31}
32
33impl ConnectionOptions {
34 pub fn hydrate_with_env(mut self, provider_env_prefix: &str) -> Self {
39 if self.api_key.is_none() {
41 let specific = format!("{}_API_KEY", provider_env_prefix);
42 self.api_key = std::env::var(&specific)
43 .ok()
44 .or_else(|| std::env::var("AI_API_KEY").ok());
45 }
46 if self.base_url.is_none() {
48 if let Ok(v) = std::env::var("AI_BASE_URL") {
49 self.base_url = Some(v);
50 }
51 }
52 if self.proxy.is_none() && !self.disable_proxy {
54 self.proxy = std::env::var("AI_PROXY_URL").ok();
55 }
56 if self.timeout.is_none() {
58 if let Ok(v) = std::env::var("AI_TIMEOUT_SECS") {
59 if let Ok(secs) = v.parse::<u64>() {
60 self.timeout = Some(Duration::from_secs(secs));
61 }
62 }
63 }
64 self
65 }
66}
67
68#[derive(Debug, Clone)]
70pub struct ResilienceConfig {
71 pub circuit_breaker: Option<CircuitBreakerConfig>,
72 pub rate_limiter: Option<RateLimiterConfig>,
73 pub backpressure: Option<BackpressureConfig>,
74 pub error_handling: Option<ErrorHandlingConfig>,
75}
76
77#[derive(Debug, Clone)]
79pub struct BackpressureConfig {
80 pub max_concurrent_requests: usize,
81}
82
83#[derive(Debug, Clone)]
85pub struct ErrorHandlingConfig {
86 pub enable_recovery: bool,
87 pub enable_monitoring: bool,
88 pub error_thresholds: ErrorThresholds,
89}
90
91impl Default for ResilienceConfig {
92 fn default() -> Self {
93 Self {
94 circuit_breaker: None,
95 rate_limiter: None,
96 backpressure: None,
97 error_handling: None,
98 }
99 }
100}
101
102impl Default for BackpressureConfig {
103 fn default() -> Self {
104 Self {
105 max_concurrent_requests: 100,
106 }
107 }
108}
109
110impl Default for ErrorHandlingConfig {
111 fn default() -> Self {
112 Self {
113 enable_recovery: true,
114 enable_monitoring: true,
115 error_thresholds: ErrorThresholds::default(),
116 }
117 }
118}
119
120impl ResilienceConfig {
121 pub fn smart_defaults() -> Self {
123 Self {
124 circuit_breaker: Some(CircuitBreakerConfig::default()),
125 rate_limiter: Some(RateLimiterConfig::default()),
126 backpressure: Some(BackpressureConfig::default()),
127 error_handling: Some(ErrorHandlingConfig::default()),
128 }
129 }
130
131 pub fn production() -> Self {
133 Self {
134 circuit_breaker: Some(CircuitBreakerConfig::production()),
135 rate_limiter: Some(RateLimiterConfig::production()),
136 backpressure: Some(BackpressureConfig {
137 max_concurrent_requests: 50,
138 }),
139 error_handling: Some(ErrorHandlingConfig {
140 enable_recovery: true,
141 enable_monitoring: true,
142 error_thresholds: ErrorThresholds {
143 error_rate_threshold: 0.05, consecutive_errors: 3,
145 time_window: Duration::from_secs(30),
146 },
147 }),
148 }
149 }
150
151 pub fn development() -> Self {
153 Self {
154 circuit_breaker: Some(CircuitBreakerConfig::development()),
155 rate_limiter: Some(RateLimiterConfig::development()),
156 backpressure: Some(BackpressureConfig {
157 max_concurrent_requests: 200,
158 }),
159 error_handling: Some(ErrorHandlingConfig {
160 enable_recovery: false,
161 enable_monitoring: false,
162 error_thresholds: ErrorThresholds::default(),
163 }),
164 }
165 }
166}