Skip to main content

cortexai_cache/
entry.rs

1//! Cache entry types
2
3use serde::{Deserialize, Serialize};
4
5/// A cached entry
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct CacheEntry {
8    /// Original query
9    pub query: String,
10    /// Context used for the query
11    pub context: String,
12    /// Cached response
13    pub response: String,
14    /// Function/tool calls made
15    pub function_calls: Vec<String>,
16    /// When the entry was created (Unix timestamp)
17    pub created_at: i64,
18    /// Number of times this entry was hit
19    pub hit_count: u32,
20    /// Optional embedding for semantic matching
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub embedding: Option<Vec<f32>>,
23}
24
25impl CacheEntry {
26    /// Create a new cache entry
27    pub fn new(
28        query: impl Into<String>,
29        context: impl Into<String>,
30        response: impl Into<String>,
31        function_calls: Vec<String>,
32    ) -> Self {
33        Self {
34            query: query.into(),
35            context: context.into(),
36            response: response.into(),
37            function_calls,
38            created_at: chrono::Utc::now().timestamp(),
39            hit_count: 0,
40            embedding: None,
41        }
42    }
43
44    /// Create with embedding for semantic matching
45    pub fn with_embedding(mut self, embedding: Vec<f32>) -> Self {
46        self.embedding = Some(embedding);
47        self
48    }
49
50    /// Increment hit count
51    pub fn record_hit(&mut self) {
52        self.hit_count += 1;
53    }
54
55    /// Check if entry is expired
56    pub fn is_expired(&self, ttl_secs: i64) -> bool {
57        let now = chrono::Utc::now().timestamp();
58        now - self.created_at > ttl_secs
59    }
60
61    /// Get age in seconds
62    pub fn age_secs(&self) -> i64 {
63        chrono::Utc::now().timestamp() - self.created_at
64    }
65}
66
67/// Statistics for cache operations
68#[derive(Debug, Clone, Default, Serialize, Deserialize)]
69pub struct CacheStats {
70    /// Total number of entries
71    pub entries: usize,
72    /// Total hits
73    pub hits: u64,
74    /// Total misses
75    pub misses: u64,
76    /// Total stores
77    pub stores: u64,
78    /// Total evictions
79    pub evictions: u64,
80}
81
82impl CacheStats {
83    /// Calculate hit rate
84    pub fn hit_rate(&self) -> f64 {
85        let total = self.hits + self.misses;
86        if total == 0 {
87            return 0.0;
88        }
89        self.hits as f64 / total as f64
90    }
91}