redis_oxide/core/
config.rs1use std::time::Duration;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
7pub enum ProtocolVersion {
8 #[default]
10 Resp2,
11 Resp3,
13}
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum PoolStrategy {
18 Multiplexed,
20 Pool,
22}
23
24#[derive(Debug, Clone)]
26pub struct PoolConfig {
27 pub strategy: PoolStrategy,
29 pub max_size: usize,
31 pub min_idle: usize,
33 pub connection_timeout: Duration,
35}
36
37impl Default for PoolConfig {
38 fn default() -> Self {
39 Self {
40 strategy: PoolStrategy::Multiplexed,
41 max_size: 10,
42 min_idle: 2,
43 connection_timeout: Duration::from_secs(5),
44 }
45 }
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum TopologyMode {
51 Auto,
53 Standalone,
55 Cluster,
57}
58
59#[derive(Debug, Clone)]
61pub struct ConnectionConfig {
62 pub connection_string: String,
64
65 pub password: Option<String>,
67
68 pub database: u8,
70
71 pub connect_timeout: Duration,
73
74 pub operation_timeout: Duration,
76
77 pub tcp_keepalive: Option<Duration>,
79
80 pub topology_mode: TopologyMode,
82
83 pub pool: PoolConfig,
85
86 pub max_redirects: usize,
88
89 pub protocol_version: ProtocolVersion,
91
92 pub sentinel: Option<crate::sentinel::SentinelConfig>,
94
95 pub reconnect: ReconnectConfig,
97}
98
99#[derive(Debug, Clone)]
101pub struct ReconnectConfig {
102 pub enabled: bool,
104
105 pub initial_delay: Duration,
107
108 pub max_delay: Duration,
110
111 pub backoff_multiplier: f64,
113
114 pub max_attempts: Option<usize>,
116}
117
118impl Default for ReconnectConfig {
119 fn default() -> Self {
120 Self {
121 enabled: true,
122 initial_delay: Duration::from_millis(100),
123 max_delay: Duration::from_secs(30),
124 backoff_multiplier: 2.0,
125 max_attempts: None,
126 }
127 }
128}
129
130impl Default for ConnectionConfig {
131 fn default() -> Self {
132 Self {
133 connection_string: "redis://localhost:6379".to_string(),
134 password: None,
135 database: 0,
136 connect_timeout: Duration::from_secs(5),
137 operation_timeout: Duration::from_secs(30),
138 tcp_keepalive: Some(Duration::from_secs(60)),
139 topology_mode: TopologyMode::Auto,
140 pool: PoolConfig::default(),
141 max_redirects: 3,
142 protocol_version: ProtocolVersion::default(),
143 sentinel: None,
144 reconnect: ReconnectConfig::default(),
145 }
146 }
147}
148
149impl ConnectionConfig {
150 pub fn new(connection_string: impl Into<String>) -> Self {
152 Self {
153 connection_string: connection_string.into(),
154 ..Default::default()
155 }
156 }
157
158 #[must_use]
160 pub fn with_password(mut self, password: impl Into<String>) -> Self {
161 self.password = Some(password.into());
162 self
163 }
164
165 #[must_use]
167 pub const fn with_database(mut self, database: u8) -> Self {
168 self.database = database;
169 self
170 }
171
172 #[must_use]
174 pub const fn with_connect_timeout(mut self, timeout: Duration) -> Self {
175 self.connect_timeout = timeout;
176 self
177 }
178
179 #[must_use]
181 pub const fn with_operation_timeout(mut self, timeout: Duration) -> Self {
182 self.operation_timeout = timeout;
183 self
184 }
185
186 #[must_use]
188 pub const fn with_topology_mode(mut self, mode: TopologyMode) -> Self {
189 self.topology_mode = mode;
190 self
191 }
192
193 #[must_use]
195 pub const fn with_pool_config(mut self, pool: PoolConfig) -> Self {
196 self.pool = pool;
197 self
198 }
199
200 #[must_use]
202 pub const fn with_max_redirects(mut self, max: usize) -> Self {
203 self.max_redirects = max;
204 self
205 }
206
207 #[must_use]
209 pub const fn with_protocol_version(mut self, version: ProtocolVersion) -> Self {
210 self.protocol_version = version;
211 self
212 }
213
214 #[must_use]
216 pub fn parse_endpoints(&self) -> Vec<(String, u16)> {
217 let conn_str = self.connection_string.trim();
218
219 let addr_part = conn_str
221 .strip_prefix("redis://")
222 .unwrap_or(conn_str)
223 .strip_prefix("rediss://")
224 .unwrap_or_else(|| conn_str.strip_prefix("redis://").unwrap_or(conn_str));
225
226 addr_part
228 .split(',')
229 .filter_map(|endpoint| {
230 let endpoint = endpoint.trim();
231 if endpoint.is_empty() {
232 return None;
233 }
234
235 if let Some((host, port_str)) = endpoint.rsplit_once(':') {
237 if let Ok(port) = port_str.parse::<u16>() {
238 return Some((host.to_string(), port));
239 }
240 }
241
242 Some((endpoint.to_string(), 6379))
244 })
245 .collect()
246 }
247}