Skip to main content

lastid_sdk/config/
cache.rs

1//! Cache configuration for trust registry.
2
3#[cfg(feature = "json-schema")]
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7use crate::error::LastIDError;
8
9/// Trust registry cache configuration.
10#[derive(Debug, Clone, Serialize, Deserialize)]
11#[cfg_attr(feature = "json-schema", derive(JsonSchema))]
12#[serde(default)]
13pub struct CacheConfig {
14    /// Enable caching (default: true)
15    #[serde(default = "default_cache_enabled")]
16    pub enabled: bool,
17
18    /// Cache TTL in seconds (default: 60)
19    #[serde(default = "default_cache_ttl")]
20    pub ttl_seconds: u64,
21
22    /// Maximum cache entries (default: 1000)
23    #[serde(default = "default_cache_max_entries")]
24    pub max_entries: usize,
25}
26
27const fn default_cache_enabled() -> bool {
28    true
29}
30const fn default_cache_ttl() -> u64 {
31    60
32}
33const fn default_cache_max_entries() -> usize {
34    1000
35}
36
37impl Default for CacheConfig {
38    fn default() -> Self {
39        Self {
40            enabled: default_cache_enabled(),
41            ttl_seconds: default_cache_ttl(),
42            max_entries: default_cache_max_entries(),
43        }
44    }
45}
46
47impl CacheConfig {
48    /// Create a disabled cache configuration.
49    #[must_use]
50    pub fn disabled() -> Self {
51        Self {
52            enabled: false,
53            ..Default::default()
54        }
55    }
56
57    /// Validate the cache configuration.
58    pub fn validate(&self) -> Result<(), LastIDError> {
59        if self.enabled {
60            if self.ttl_seconds == 0 {
61                return Err(LastIDError::config("cache ttl_seconds must be > 0"));
62            }
63
64            if self.ttl_seconds > 3600 {
65                return Err(LastIDError::config(
66                    "cache ttl_seconds must be <= 3600 (1 hour)",
67                ));
68            }
69
70            if self.max_entries == 0 {
71                return Err(LastIDError::config("cache max_entries must be > 0"));
72            }
73        }
74
75        Ok(())
76    }
77
78    /// Merge another configuration into this one.
79    pub const fn merge(&mut self, other: &Self) {
80        if !other.enabled {
81            self.enabled = false;
82        }
83        if other.ttl_seconds != default_cache_ttl() {
84            self.ttl_seconds = other.ttl_seconds;
85        }
86        if other.max_entries != default_cache_max_entries() {
87            self.max_entries = other.max_entries;
88        }
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn test_default_values() {
98        let config = CacheConfig::default();
99        assert!(config.enabled);
100        assert_eq!(config.ttl_seconds, 60);
101        assert_eq!(config.max_entries, 1000);
102    }
103
104    #[test]
105    fn test_disabled() {
106        let config = CacheConfig::disabled();
107        assert!(!config.enabled);
108    }
109
110    #[test]
111    fn test_validate_valid() {
112        let config = CacheConfig::default();
113        assert!(config.validate().is_ok());
114
115        let disabled = CacheConfig::disabled();
116        assert!(disabled.validate().is_ok());
117    }
118
119    #[test]
120    fn test_validate_invalid_ttl() {
121        let mut config = CacheConfig::default();
122        config.ttl_seconds = 0;
123        assert!(config.validate().is_err());
124
125        config.ttl_seconds = 7200; // > 1 hour
126        assert!(config.validate().is_err());
127    }
128
129    #[test]
130    fn test_validate_invalid_max_entries() {
131        let mut config = CacheConfig::default();
132        config.max_entries = 0;
133        assert!(config.validate().is_err());
134    }
135}