in_memory_cache/
config.rs

1//! Configuration for the in-memory cache.
2//!
3//! This module provides a builder pattern for configuring cache behavior
4//! including capacity limits, TTL defaults, and cleanup intervals.
5
6use std::time::Duration;
7
8/// Configuration for creating a new cache instance.
9///
10/// Use the builder pattern to construct configuration:
11///
12/// ```
13/// use in_memory_cache::CacheConfig;
14/// use std::time::Duration;
15///
16/// let config = CacheConfig::new()
17///     .max_capacity(10_000)
18///     .default_ttl(Duration::from_secs(300))
19///     .build();
20/// ```
21#[derive(Debug, Clone)]
22pub struct CacheConfig {
23    /// Maximum number of entries the cache can hold.
24    /// When this limit is reached, the least recently used entry is evicted.
25    /// `None` means unlimited (not recommended for production).
26    pub(crate) max_capacity: Option<usize>,
27
28    /// Default TTL for entries when not explicitly specified.
29    /// `None` means entries don't expire by default.
30    pub(crate) default_ttl: Option<Duration>,
31
32    /// Interval for background cleanup of expired entries.
33    /// `None` disables background cleanup (lazy expiration only).
34    pub(crate) cleanup_interval: Option<Duration>,
35
36    /// Whether to enable background cleanup task.
37    pub(crate) background_cleanup: bool,
38}
39
40impl Default for CacheConfig {
41    fn default() -> Self {
42        Self {
43            max_capacity: None,
44            default_ttl: None,
45            cleanup_interval: Some(Duration::from_secs(60)),
46            background_cleanup: false,
47        }
48    }
49}
50
51impl CacheConfig {
52    /// Create a new configuration builder with default values.
53    pub fn new() -> Self {
54        Self::default()
55    }
56
57    /// Set the maximum capacity of the cache.
58    ///
59    /// When the cache reaches this capacity, the least recently used
60    /// entry will be evicted to make room for new entries.
61    ///
62    /// # Arguments
63    /// * `capacity` - Maximum number of entries. Use 0 for unlimited (not recommended).
64    pub fn max_capacity(mut self, capacity: usize) -> Self {
65        self.max_capacity = if capacity == 0 { None } else { Some(capacity) };
66        self
67    }
68
69    /// Set the default TTL for entries.
70    ///
71    /// Entries without an explicit TTL will use this value.
72    /// Set to `Duration::ZERO` to disable default TTL.
73    pub fn default_ttl(mut self, ttl: Duration) -> Self {
74        self.default_ttl = if ttl.is_zero() { None } else { Some(ttl) };
75        self
76    }
77
78    /// Set the interval for background cleanup of expired entries.
79    ///
80    /// The background task will run at this interval to remove expired entries.
81    /// This is in addition to lazy expiration (entries checked on access).
82    pub fn cleanup_interval(mut self, interval: Duration) -> Self {
83        self.cleanup_interval = if interval.is_zero() {
84            None
85        } else {
86            Some(interval)
87        };
88        self
89    }
90
91    /// Enable or disable background cleanup.
92    ///
93    /// When enabled, a background task periodically removes expired entries.
94    /// When disabled, entries are only removed on access (lazy expiration).
95    pub fn background_cleanup(mut self, enabled: bool) -> Self {
96        self.background_cleanup = enabled;
97        self
98    }
99
100    /// Build the final configuration.
101    ///
102    /// This method validates the configuration and returns the final config.
103    pub fn build(self) -> Self {
104        self
105    }
106
107    /// Get the maximum capacity, if set.
108    pub fn get_max_capacity(&self) -> Option<usize> {
109        self.max_capacity
110    }
111
112    /// Get the default TTL, if set.
113    pub fn get_default_ttl(&self) -> Option<Duration> {
114        self.default_ttl
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121
122    #[test]
123    fn test_default_config() {
124        let config = CacheConfig::default();
125        assert!(config.max_capacity.is_none());
126        assert!(config.default_ttl.is_none());
127        assert!(!config.background_cleanup);
128    }
129
130    #[test]
131    fn test_builder_pattern() {
132        let config = CacheConfig::new()
133            .max_capacity(1000)
134            .default_ttl(Duration::from_secs(60))
135            .background_cleanup(true)
136            .build();
137
138        assert_eq!(config.max_capacity, Some(1000));
139        assert_eq!(config.default_ttl, Some(Duration::from_secs(60)));
140        assert!(config.background_cleanup);
141    }
142
143    #[test]
144    fn test_zero_capacity_means_unlimited() {
145        let config = CacheConfig::new().max_capacity(0).build();
146        assert!(config.max_capacity.is_none());
147    }
148
149    #[test]
150    fn test_zero_ttl_means_no_default() {
151        let config = CacheConfig::new().default_ttl(Duration::ZERO).build();
152        assert!(config.default_ttl.is_none());
153    }
154}