1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
//! Builder preset configurations for common use cases.
use core::time::Duration;
use super::ClientBuilder;
impl ClientBuilder
{
/// Create a development configuration preset with common development settings.
///
/// This preset includes:
/// - Extended timeout for debugging
/// - Reduced rate limits for development
/// - Disabled circuit breaker for easier testing
/// - Enhanced logging when available
#[ must_use ]
#[ inline ]
pub fn development_preset( mut self ) -> Self
{
self.timeout = Duration::from_secs( 120 ); // Extended timeout for debugging
#[ cfg( feature = "retry" ) ]
{
self.max_retries = 1; // Faster failures in development
self.base_delay = Duration::from_millis( 50 ); // Shorter delays
}
#[ cfg( feature = "circuit_breaker" ) ]
{
self.enable_circuit_breaker = false; // Disable circuit breaker for easier testing
}
#[ cfg( feature = "rate_limiting" ) ]
{
self.enable_rate_limiting = false; // Disable rate limiting in development
}
self
}
/// Create a production configuration preset with optimized production settings.
///
/// This preset includes:
/// - Conservative timeouts for stability
/// - Aggressive retry logic
/// - Circuit breaker enabled
/// - Rate limiting enabled
/// - Caching enabled for performance
#[ must_use ]
#[ inline ]
pub fn production_preset( mut self ) -> Self
{
self.timeout = Duration::from_secs( 30 ); // Conservative timeout
#[ cfg( feature = "retry" ) ]
{
self.max_retries = 5; // Aggressive retries
self.base_delay = Duration::from_millis( 100 );
self.max_delay = Duration::from_secs( 10 );
self.enable_jitter = true;
self.backoff_multiplier = 2.0;
self.enable_retry_metrics = true;
}
#[ cfg( feature = "circuit_breaker" ) ]
{
self.enable_circuit_breaker = true;
self.circuit_breaker_failure_threshold = 3;
self.circuit_breaker_success_threshold = 2;
self.circuit_breaker_timeout = Duration::from_secs( 30 );
self.enable_circuit_breaker_metrics = true;
}
#[ cfg( feature = "caching" ) ]
{
self.enable_request_cache = true;
self.cache_ttl = Duration::from_secs( 300 );
self.cache_max_size = 1000;
self.enable_cache_metrics = true;
}
#[ cfg( feature = "rate_limiting" ) ]
{
self.enable_rate_limiting = true;
self.rate_limit_requests_per_second = 5.0; // Conservative rate limit
self.rate_limit_algorithm = "token_bucket".to_string();
self.enable_rate_limiting_metrics = true;
}
self
}
/// Create a high-performance configuration preset optimized for throughput.
///
/// This preset includes:
/// - Shorter timeouts for faster failures
/// - Minimal retry logic
/// - Aggressive rate limits
/// - Optimized caching
#[ must_use ]
#[ inline ]
pub fn high_performance_preset( mut self ) -> Self
{
self.timeout = Duration::from_secs( 10 ); // Short timeout for high throughput
#[ cfg( feature = "retry" ) ]
{
self.max_retries = 1; // Minimal retries for speed
self.base_delay = Duration::from_millis( 10 );
self.max_delay = Duration::from_secs( 1 );
self.enable_jitter = false; // Disable jitter for consistency
self.backoff_multiplier = 1.5;
}
#[ cfg( feature = "circuit_breaker" ) ]
{
self.enable_circuit_breaker = true;
self.circuit_breaker_failure_threshold = 10; // Higher threshold
self.circuit_breaker_success_threshold = 1; // Quick recovery
self.circuit_breaker_timeout = Duration::from_secs( 5 );
}
#[ cfg( feature = "caching" ) ]
{
self.enable_request_cache = true;
self.cache_ttl = Duration::from_secs( 60 ); // Shorter TTL for freshness
self.cache_max_size = 5000; // Larger cache
self.enable_cache_metrics = true;
}
#[ cfg( feature = "rate_limiting" ) ]
{
self.enable_rate_limiting = true;
self.rate_limit_requests_per_second = 50.0; // High rate limit
self.rate_limit_algorithm = "adaptive".to_string();
self.enable_rate_limiting_metrics = true;
}
self
}
/// Configure the client for testing with sensible test defaults.
///
/// This preset includes:
/// - Very short timeouts for fast test execution
/// - No retries for predictable behavior
/// - All features disabled by default
/// - Deterministic configuration
#[ must_use ]
#[ inline ]
pub fn testing_preset( mut self ) -> Self
{
self.timeout = Duration::from_millis( 100 ); // Very short timeout for tests
#[ cfg( feature = "retry" ) ]
{
self.max_retries = 0; // No retries in tests
self.base_delay = Duration::from_millis( 1 );
self.max_delay = Duration::from_millis( 2 ); // Must be greater than base_delay
self.enable_jitter = false; // Deterministic behavior
self.backoff_multiplier = 1.1; // Minimal but valid backoff multiplier
self.enable_retry_metrics = false;
}
#[ cfg( feature = "circuit_breaker" ) ]
{
self.enable_circuit_breaker = false; // Disable for predictable tests
}
#[ cfg( feature = "caching" ) ]
{
self.enable_request_cache = false; // Disable caching in tests
}
#[ cfg( feature = "rate_limiting" ) ]
{
self.enable_rate_limiting = false; // Disable rate limiting in tests
}
self
}
/// Apply conditional configuration based on environment or runtime conditions.
///
/// This method allows for dynamic configuration based on external factors
/// while maintaining the builder pattern's fluent interface.
///
/// # Arguments
///
/// * `condition` - Boolean condition to evaluate
/// * `configure_fn` - Function to apply configuration when condition is true
#[ must_use ]
#[ inline ]
pub fn when< F >( self, condition : bool, configure_fn : F ) -> Self
where
F : FnOnce( ClientBuilder ) -> ClientBuilder,
{
if condition
{
configure_fn( self )
}
else
{
self
}
}
/// Apply configuration from environment variables with fallbacks.
///
/// This method reads common configuration from environment variables
/// and applies them to the builder, maintaining defaults when variables
/// are not present.
#[ must_use ]
#[ inline ]
pub fn from_environment( mut self ) -> Self
{
// Read timeout from environment
if let Ok( timeout_str ) = std::env::var( "GEMINI_TIMEOUT_SECONDS" )
{
if let Ok( timeout_secs ) = timeout_str.parse::< u64 >()
{
self.timeout = Duration::from_secs( timeout_secs );
}
}
// Read base URL from environment
if let Ok( base_url ) = std::env::var( "GEMINI_BASE_URL" )
{
if !base_url.is_empty()
{
self.base_url = base_url;
}
}
// Read feature configurations from environment
#[ cfg( feature = "retry" ) ]
{
if let Ok( max_retries_str ) = std::env::var( "GEMINI_MAX_RETRIES" )
{
if let Ok( max_retries ) = max_retries_str.parse::< u32 >()
{
self.max_retries = max_retries;
}
}
}
#[ cfg( feature = "rate_limiting" ) ]
{
if let Ok( rps_str ) = std::env::var( "GEMINI_RATE_LIMIT_RPS" )
{
if let Ok( rps ) = rps_str.parse::< f64 >()
{
if rps > 0.0
{
self.enable_rate_limiting = true;
self.rate_limit_requests_per_second = rps;
}
}
}
}
self
}
}