1#[cfg(feature = "cache-memory")]
6pub mod memory;
7
8#[cfg(feature = "cache-redis")]
9pub mod redis;
10
11use std::time::Duration;
12
13#[async_trait::async_trait]
15pub trait Cache: Send + Sync {
16 async fn get(&self, key: &str) -> Option<String>;
18
19 async fn set(&self, key: String, value: String, ttl: Option<Duration>);
21
22 async fn delete(&self, key: &str);
24
25 async fn clear(&self);
27
28 async fn exists(&self, key: &str) -> bool;
30}
31
32#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
34pub struct CacheConfig {
35 pub cache_type: String,
37
38 pub memory_size: Option<usize>,
40
41 pub redis_url: Option<String>,
43
44 pub default_ttl: Option<u64>,
46}
47
48impl Default for CacheConfig {
49 fn default() -> Self {
50 Self {
51 cache_type: "memory".to_string(),
52 memory_size: Some(1000),
53 redis_url: None,
54 default_ttl: Some(3600), }
56 }
57}
58
59pub fn create_cache(config: &CacheConfig) -> Result<Box<dyn Cache>, crate::error::Error> {
65 match config.cache_type.as_str() {
66 "memory" => {
67 #[cfg(feature = "cache-memory")]
68 {
69 let size = config.memory_size.unwrap_or(1000);
70 Ok(Box::new(memory::MemoryCache::new(size)))
71 }
72 #[cfg(not(feature = "cache-memory"))]
73 {
74 Err(crate::error::Error::Config(
75 "memory cache feature is not enabled".to_string(),
76 ))
77 }
78 }
79 "redis" => {
80 #[cfg(feature = "cache-redis")]
81 {
82 Err(crate::error::Error::Config(
85 "Redis cache requires async initialization. Use create_cache_async instead."
86 .to_string(),
87 ))
88 }
89 #[cfg(not(feature = "cache-redis"))]
90 {
91 Err(crate::error::Error::Config(
92 "redis cache feature is not enabled".to_string(),
93 ))
94 }
95 }
96 _ => Err(crate::error::Error::Config(format!(
97 "unsupported cache type: {}",
98 config.cache_type
99 ))),
100 }
101}
102
103#[cfg(feature = "cache-redis")]
109pub async fn create_cache_async(
110 config: &CacheConfig,
111) -> Result<Box<dyn Cache>, crate::error::Error> {
112 match config.cache_type.as_str() {
113 "memory" => {
114 let size = config.memory_size.unwrap_or(1000);
115 Ok(Box::new(memory::MemoryCache::new(size)))
116 }
117 "redis" => {
118 let url = config
119 .redis_url
120 .as_ref()
121 .ok_or_else(|| crate::error::Error::Config("redis_url is required".to_string()))?;
122 Ok(Box::new(redis::RedisCache::new(url).await?))
123 }
124 _ => Err(crate::error::Error::Config(format!(
125 "unsupported cache type: {}",
126 config.cache_type
127 ))),
128 }
129}