1use crate::{Error, RateLimitConfig, CacheConfig, MetricsCollector, validation::Validator};
2use reqwest::Client as HttpClient;
3use std::sync::Arc;
4use std::time::Duration;
5
6#[derive(Debug, Clone)]
8pub struct ClientConfig {
9 pub base_url: String,
12
13 pub timeout: Duration,
15
16 pub max_retries: u8,
18
19 pub user_agent: String,
21
22 pub rate_limit: RateLimitConfig,
24
25 pub cache: CacheConfig,
27
28 pub enable_logging: bool,
30
31 pub enable_metrics: bool,
33
34 pub connection_pool_size: usize,
36
37 pub keep_alive_timeout: Duration,
39}
40
41impl Default for ClientConfig {
42 fn default() -> Self {
43 Self {
44 base_url: "https://api.goldrush.dev".to_string(),
46 timeout: Duration::from_secs(30),
47 max_retries: 3,
48 user_agent: format!("goldrush-sdk-rs/{}", env!("CARGO_PKG_VERSION")),
49 rate_limit: RateLimitConfig::default(),
50 cache: CacheConfig::default(),
51 enable_logging: true,
52 enable_metrics: true,
53 connection_pool_size: 10,
54 keep_alive_timeout: Duration::from_secs(90),
55 }
56 }
57}
58
59impl ClientConfig {
60 pub fn new<S: Into<String>>(base_url: S) -> Self {
62 Self {
63 base_url: base_url.into(),
64 ..Default::default()
65 }
66 }
67
68 pub fn with_timeout(mut self, timeout: Duration) -> Self {
70 self.timeout = timeout;
71 self
72 }
73
74 pub fn with_max_retries(mut self, max_retries: u8) -> Self {
76 self.max_retries = max_retries;
77 self
78 }
79
80 pub fn with_user_agent<S: Into<String>>(mut self, user_agent: S) -> Self {
82 self.user_agent = user_agent.into();
83 self
84 }
85}
86
87pub struct GoldRushClient {
89 pub(crate) http: HttpClient,
90 pub(crate) api_key: String,
91 pub(crate) config: ClientConfig,
92 pub(crate) metrics: Option<Arc<MetricsCollector>>,
93}
94
95impl GoldRushClient {
96 pub fn new<S: Into<String>>(api_key: S, config: ClientConfig) -> Result<Self, Error> {
112 let api_key = api_key.into();
113
114 Validator::validate_api_key(&api_key)?;
116
117 Validator::validate_url(&config.base_url)?;
119
120 let http = HttpClient::builder()
121 .user_agent(&config.user_agent)
122 .timeout(config.timeout)
123 .pool_max_idle_per_host(config.connection_pool_size)
124 .pool_idle_timeout(config.keep_alive_timeout)
125 .tcp_keepalive(Some(Duration::from_secs(60)))
126 .build()?;
127
128 let metrics = if config.enable_metrics {
129 Some(Arc::new(MetricsCollector::new()))
130 } else {
131 None
132 };
133
134 Ok(Self {
135 http,
136 api_key,
137 config,
138 metrics
139 })
140 }
141
142 pub fn with_key<S: Into<String>>(api_key: S) -> Result<Self, Error> {
157 Self::new(api_key, ClientConfig::default())
158 }
159
160 pub fn metrics(&self) -> Option<&Arc<MetricsCollector>> {
162 self.metrics.as_ref()
163 }
164}