litellm_rs/core/traits/
cache.rs

1//! Cache system trait definitions
2//!
3//! Provides unified cache interface supporting multiple cache backends
4
5use async_trait::async_trait;
6use serde::{Deserialize, Serialize};
7use std::time::Duration;
8
9/// Core cache trait
10///
11/// Defines unified cache operation interface
12#[async_trait]
13pub trait Cache<K, V>: Send + Sync
14where
15    K: Send + Sync,
16    V: Send + Sync,
17{
18    /// Error
19    type Error: std::error::Error + Send + Sync + 'static;
20
21    /// Get
22    async fn get(&self, key: &K) -> Result<Option<V>, Self::Error>;
23
24    /// Settings
25    async fn set(&self, key: &K, value: V, ttl: Duration) -> Result<(), Self::Error>;
26
27    /// Delete
28    async fn delete(&self, key: &K) -> Result<bool, Self::Error>;
29
30    /// Check
31    async fn exists(&self, key: &K) -> Result<bool, Self::Error>;
32
33    /// Settings
34    async fn expire(&self, key: &K, ttl: Duration) -> Result<bool, Self::Error>;
35
36    /// Get
37    async fn ttl(&self, key: &K) -> Result<Option<Duration>, Self::Error>;
38
39    /// Clear all cache
40    async fn clear(&self) -> Result<(), Self::Error>;
41
42    /// Get
43    async fn size(&self) -> Result<usize, Self::Error>;
44
45    /// Get
46    async fn get_many(&self, keys: &[K]) -> Result<Vec<Option<V>>, Self::Error> {
47        let mut results = Vec::with_capacity(keys.len());
48        for key in keys {
49            results.push(self.get(key).await?);
50        }
51        Ok(results)
52    }
53
54    /// Settings
55    async fn set_many(&self, items: &[(K, V, Duration)]) -> Result<(), Self::Error>
56    where
57        K: Clone,
58        V: Clone,
59    {
60        for (key, value, ttl) in items {
61            self.set(key, value.clone(), *ttl).await?;
62        }
63        Ok(())
64    }
65}
66
67/// Cache key trait
68///
69/// Defines operations that cache keys must support
70pub trait CacheKey: Send + Sync + Clone + std::fmt::Debug + std::hash::Hash + Eq {
71    /// Serialize key to string
72    fn to_cache_key(&self) -> String;
73
74    /// Deserialize key from string
75    fn from_cache_key(s: &str) -> Result<Self, CacheError>
76    where
77        Self: Sized;
78}
79
80/// Cache value trait
81///
82/// Defines operations that cache values must support
83pub trait CacheValue: Send + Sync + Clone + std::fmt::Debug {
84    /// Serialize to bytes
85    fn to_bytes(&self) -> Result<Vec<u8>, CacheError>;
86
87    /// Deserialize from bytes
88    fn from_bytes(bytes: &[u8]) -> Result<Self, CacheError>
89    where
90        Self: Sized;
91}
92
93/// Implementation of CacheKey for String
94impl CacheKey for String {
95    fn to_cache_key(&self) -> String {
96        self.clone()
97    }
98
99    fn from_cache_key(s: &str) -> Result<Self, CacheError> {
100        Ok(s.to_string())
101    }
102}
103
104/// Implementation of CacheValue for all types that implement Serialize + DeserializeOwned
105impl<T> CacheValue for T
106where
107    T: Serialize + for<'de> Deserialize<'de> + Send + Sync + Clone + std::fmt::Debug,
108{
109    fn to_bytes(&self) -> Result<Vec<u8>, CacheError> {
110        bincode::serialize(self).map_err(CacheError::Serialization)
111    }
112
113    fn from_bytes(bytes: &[u8]) -> Result<Self, CacheError> {
114        bincode::deserialize(bytes).map_err(CacheError::Deserialization)
115    }
116}
117
118/// Cache statistics
119#[derive(Debug, Clone)]
120pub struct CacheStats {
121    /// Cache hit count
122    pub hits: u64,
123    /// Cache miss count
124    pub misses: u64,
125    /// Current key count
126    pub key_count: usize,
127    /// Used memory amount (bytes)
128    pub memory_usage: usize,
129    /// Hit rate
130    pub hit_rate: f64,
131}
132
133impl CacheStats {
134    pub fn new() -> Self {
135        Self {
136            hits: 0,
137            misses: 0,
138            key_count: 0,
139            memory_usage: 0,
140            hit_rate: 0.0,
141        }
142    }
143
144    pub fn calculate_hit_rate(&mut self) {
145        let total = self.hits + self.misses;
146        if total > 0 {
147            self.hit_rate = self.hits as f64 / total as f64;
148        }
149    }
150}
151
152impl Default for CacheStats {
153    fn default() -> Self {
154        Self::new()
155    }
156}
157
158/// Cache trait with statistics functionality
159#[async_trait]
160pub trait CacheWithStats<K, V>: Cache<K, V>
161where
162    K: Send + Sync,
163    V: Send + Sync,
164{
165    /// Get
166    async fn stats(&self) -> Result<CacheStats, Self::Error>;
167
168    /// Reset statistics
169    async fn reset_stats(&self) -> Result<(), Self::Error>;
170}
171
172/// Cache event types
173#[derive(Debug, Clone)]
174pub enum CacheEvent<K, V> {
175    /// Cache hit
176    Hit { key: K },
177    /// Cache miss
178    Miss { key: K },
179    /// Settings
180    Set { key: K, value: V },
181    /// Delete
182    Delete { key: K },
183    /// Cache expiration
184    Expire { key: K },
185    /// Cache clear
186    Clear,
187}
188
189/// Cache event listener
190#[async_trait]
191pub trait CacheEventListener<K, V>: Send + Sync
192where
193    K: Send + Sync,
194    V: Send + Sync,
195{
196    /// Handle
197    async fn on_event(&self, event: CacheEvent<K, V>);
198}
199
200/// Error
201#[derive(Debug, thiserror::Error)]
202pub enum CacheError {
203    #[error("Connection failed: {0}")]
204    Connection(String),
205
206    #[error("Serialization failed: {0}")]
207    Serialization(#[from] Box<bincode::ErrorKind>),
208
209    #[error("Deserialization failed: {0}")]
210    Deserialization(Box<bincode::ErrorKind>),
211
212    #[error("Key not found: {key}")]
213    KeyNotFound { key: String },
214
215    #[error("Cache is full")]
216    CacheFull,
217
218    #[error("Invalid TTL: {ttl_ms}ms")]
219    InvalidTTL { ttl_ms: u64 },
220
221    #[error("Cache operation timeout")]
222    Timeout,
223
224    #[error("Cache backend error: {0}")]
225    Backend(String),
226
227    #[error("Other cache error: {0}")]
228    Other(String),
229}
230
231impl CacheError {
232    pub fn connection(msg: impl Into<String>) -> Self {
233        Self::Connection(msg.into())
234    }
235
236    pub fn key_not_found(key: impl Into<String>) -> Self {
237        Self::KeyNotFound { key: key.into() }
238    }
239
240    pub fn backend(msg: impl Into<String>) -> Self {
241        Self::Backend(msg.into())
242    }
243
244    pub fn other(msg: impl Into<String>) -> Self {
245        Self::Other(msg.into())
246    }
247}