vtcode_core/tools/
cache.rs1use super::types::{EnhancedCacheEntry, EnhancedCacheStats};
4use once_cell::sync::Lazy;
5use quick_cache::sync::Cache;
6use serde_json::Value;
7use std::sync::Arc;
8use std::time::Duration;
9
10pub static FILE_CACHE: Lazy<FileCache> = Lazy::new(|| FileCache::new(1000));
12
13pub struct FileCache {
15 file_cache: Arc<Cache<String, EnhancedCacheEntry<Value>>>,
16 directory_cache: Arc<Cache<String, EnhancedCacheEntry<Value>>>,
17 stats: Arc<std::sync::Mutex<EnhancedCacheStats>>,
18 max_size_bytes: usize,
19 ttl: Duration,
20}
21
22impl FileCache {
23 pub fn new(capacity: usize) -> Self {
24 Self {
25 file_cache: Arc::new(Cache::new(capacity)),
26 directory_cache: Arc::new(Cache::new(capacity / 2)),
27 stats: Arc::new(std::sync::Mutex::new(EnhancedCacheStats::default())),
28 max_size_bytes: 50 * 1024 * 1024, ttl: Duration::from_secs(300), }
31 }
32
33 pub async fn get_file(&self, key: &str) -> Option<Value> {
35 let mut stats = self.stats.lock().unwrap();
36
37 if let Some(entry) = self.file_cache.get(key) {
38 if entry.timestamp.elapsed() < self.ttl {
40 stats.hits += 1;
42 return Some(entry.data.clone());
43 } else {
44 self.file_cache.remove(key);
46 stats.expired_evictions += 1;
47 }
48 }
49
50 stats.misses += 1;
51 None
52 }
53
54 pub async fn put_file(&self, key: String, value: Value) {
56 let size_bytes = serde_json::to_string(&value).unwrap_or_default().len();
57 let entry = EnhancedCacheEntry::new(value, size_bytes);
58
59 let mut stats = self.stats.lock().unwrap();
60
61 if stats.total_size_bytes + size_bytes > self.max_size_bytes {
63 stats.memory_evictions += 1;
64 }
65
66 self.file_cache.insert(key, entry);
67 stats.entries = self.file_cache.len();
68 stats.total_size_bytes += size_bytes;
69 }
70
71 pub async fn get_directory(&self, key: &str) -> Option<Value> {
73 let mut stats = self.stats.lock().unwrap();
74
75 if let Some(entry) = self.directory_cache.get(key) {
76 if entry.timestamp.elapsed() < self.ttl {
77 stats.hits += 1;
78 return Some(entry.data.clone());
79 } else {
80 self.directory_cache.remove(key);
81 stats.expired_evictions += 1;
82 }
83 }
84
85 stats.misses += 1;
86 None
87 }
88
89 pub async fn put_directory(&self, key: String, value: Value) {
91 let size_bytes = serde_json::to_string(&value).unwrap_or_default().len();
92 let entry = EnhancedCacheEntry::new(value, size_bytes);
93
94 let mut stats = self.stats.lock().unwrap();
95
96 self.directory_cache.insert(key, entry);
97 stats.entries += self.directory_cache.len();
98 stats.total_size_bytes += size_bytes;
99 }
100
101 pub async fn stats(&self) -> EnhancedCacheStats {
103 self.stats.lock().unwrap().clone()
104 }
105
106 pub async fn clear(&self) {
108 self.file_cache.clear();
109 self.directory_cache.clear();
110 *self.stats.lock().unwrap() = EnhancedCacheStats::default();
111 }
112
113 pub fn capacity(&self) -> (usize, usize) {
115 (
116 self.file_cache.capacity().try_into().unwrap_or(0),
117 self.directory_cache.capacity().try_into().unwrap_or(0),
118 )
119 }
120
121 pub fn len(&self) -> (usize, usize) {
123 (self.file_cache.len(), self.directory_cache.len())
124 }
125}