Skip to main content

aa_storage_redis/
config.rs

1//! Connection configuration for the Redis storage driver.
2//!
3//! Deserialized from the `[storage.redis]` TOML subsection.
4
5use serde::{Deserialize, Serialize};
6
7/// Settings for the `[storage.redis]` subsection of `agent-assembly.toml`.
8///
9/// ```toml
10/// [storage.redis]
11/// url = "redis://cache.internal:6379"
12/// pool_size = 16
13/// tls = false
14/// ```
15///
16/// All fields fall back to [`Default`] when omitted.
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
18#[serde(default)]
19pub struct RedisStorageConfig {
20    /// Redis connection URL. A `redis://` scheme connects in the clear; a
21    /// `rediss://` scheme (or [`tls = true`](Self::tls)) connects over TLS.
22    pub url: String,
23    /// Maximum number of pooled connections.
24    pub pool_size: usize,
25    /// When `true`, force a TLS connection by upgrading a `redis://` URL to
26    /// `rediss://` (see [`connection_url`](Self::connection_url)). A URL that is
27    /// already `rediss://` connects over TLS regardless of this flag.
28    pub tls: bool,
29}
30
31impl Default for RedisStorageConfig {
32    fn default() -> Self {
33        Self {
34            url: "redis://127.0.0.1:6379".to_owned(),
35            pool_size: 10,
36            tls: false,
37        }
38    }
39}
40
41impl RedisStorageConfig {
42    /// Return the effective connection URL, upgrading a plaintext `redis://`
43    /// URL to `rediss://` when [`tls`](Self::tls) is set. URLs that already use
44    /// a `rediss://` scheme, or any non-`redis://` scheme, are returned
45    /// unchanged.
46    pub fn connection_url(&self) -> String {
47        if self.tls {
48            if let Some(rest) = self.url.strip_prefix("redis://") {
49                return format!("rediss://{rest}");
50            }
51        }
52        self.url.clone()
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[derive(serde::Deserialize)]
61    struct Storage {
62        redis: RedisStorageConfig,
63    }
64    #[derive(serde::Deserialize)]
65    struct Root {
66        storage: Storage,
67    }
68
69    #[test]
70    fn parses_storage_redis_subsection() {
71        let src = r#"
72[storage.redis]
73url = "rediss://cache.internal:6380"
74pool_size = 32
75tls = true
76"#;
77        let root: Root = toml::from_str(src).unwrap();
78        assert_eq!(root.storage.redis.url, "rediss://cache.internal:6380");
79        assert_eq!(root.storage.redis.pool_size, 32);
80        assert!(root.storage.redis.tls);
81    }
82
83    #[test]
84    fn applies_defaults_for_missing_fields() {
85        let cfg: RedisStorageConfig = toml::from_str("").unwrap();
86        assert_eq!(cfg, RedisStorageConfig::default());
87        assert_eq!(cfg.connection_url(), "redis://127.0.0.1:6379");
88    }
89
90    #[test]
91    fn tls_toggle_upgrades_scheme() {
92        let cfg = RedisStorageConfig {
93            tls: true,
94            ..Default::default()
95        };
96        assert_eq!(cfg.connection_url(), "rediss://127.0.0.1:6379");
97    }
98}