allframe_core/cache/
mod.rs

1//! Cache abstraction for AllFrame applications
2//!
3//! This module provides a unified cache interface with support for multiple
4//! backends including in-memory caching and Redis.
5//!
6//! # Example
7//!
8//! ```rust,ignore
9//! use allframe_core::cache::{Cache, MemoryCache};
10//! use std::time::Duration;
11//!
12//! #[tokio::main]
13//! async fn main() {
14//!     let cache = MemoryCache::new();
15//!
16//!     // Set a value with TTL
17//!     cache.set("key", &"value", Some(Duration::from_secs(60))).await;
18//!
19//!     // Get the value
20//!     let value: Option<String> = cache.get("key").await;
21//!     assert_eq!(value, Some("value".to_string()));
22//! }
23//! ```
24
25mod memory;
26mod traits;
27
28pub use memory::MemoryCache;
29pub use traits::*;
30
31/// Cache key generation trait
32///
33/// Implement this trait for types that can be used as cache keys.
34pub trait CacheKey {
35    /// Generate the cache key string
36    fn cache_key(&self) -> String;
37}
38
39impl CacheKey for String {
40    fn cache_key(&self) -> String {
41        self.clone()
42    }
43}
44
45impl CacheKey for &str {
46    fn cache_key(&self) -> String {
47        (*self).to_string()
48    }
49}
50
51impl CacheKey for u64 {
52    fn cache_key(&self) -> String {
53        self.to_string()
54    }
55}
56
57impl CacheKey for i64 {
58    fn cache_key(&self) -> String {
59        self.to_string()
60    }
61}
62
63/// Cache configuration
64#[derive(Debug, Clone, Default)]
65pub struct CacheConfig {
66    /// Key prefix for namespacing
67    pub prefix: Option<String>,
68    /// Default TTL for entries
69    pub default_ttl: Option<std::time::Duration>,
70    /// Maximum number of entries (for memory cache)
71    pub max_entries: Option<usize>,
72}
73
74impl CacheConfig {
75    /// Create a new cache configuration
76    pub fn new() -> Self {
77        Self::default()
78    }
79
80    /// Set the key prefix
81    pub fn prefix(mut self, prefix: impl Into<String>) -> Self {
82        self.prefix = Some(prefix.into());
83        self
84    }
85
86    /// Set the default TTL
87    pub fn default_ttl(mut self, ttl: std::time::Duration) -> Self {
88        self.default_ttl = Some(ttl);
89        self
90    }
91
92    /// Set the maximum number of entries
93    pub fn max_entries(mut self, max: usize) -> Self {
94        self.max_entries = Some(max);
95        self
96    }
97
98    /// Build a prefixed key
99    pub fn build_key(&self, key: &str) -> String {
100        match &self.prefix {
101            Some(prefix) => format!("{}:{}", prefix, key),
102            None => key.to_string(),
103        }
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110
111    #[test]
112    fn test_cache_key_string() {
113        let key = "test".to_string();
114        assert_eq!(key.cache_key(), "test");
115    }
116
117    #[test]
118    fn test_cache_key_str() {
119        let key = "test";
120        assert_eq!(key.cache_key(), "test");
121    }
122
123    #[test]
124    fn test_cache_key_u64() {
125        let key: u64 = 42;
126        assert_eq!(key.cache_key(), "42");
127    }
128
129    #[test]
130    fn test_cache_config_prefix() {
131        let config = CacheConfig::new().prefix("myapp");
132        assert_eq!(config.build_key("user:1"), "myapp:user:1");
133    }
134
135    #[test]
136    fn test_cache_config_no_prefix() {
137        let config = CacheConfig::new();
138        assert_eq!(config.build_key("user:1"), "user:1");
139    }
140}