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}