xz_skill/cache/
tool_cache.rs1use std::collections::HashMap;
2use std::hash::{DefaultHasher, Hash, Hasher};
3use std::sync::RwLock;
4use std::time::{Duration, Instant};
5
6#[derive(Debug)]
8pub struct ToolResultCache {
9 entries: RwLock<HashMap<String, CacheEntry>>,
10 ttl: Duration,
11}
12
13#[derive(Debug, Clone)]
14struct CacheEntry {
15 value: serde_json::Value,
16 created_at: Instant,
17}
18
19impl ToolResultCache {
20 pub fn new(ttl_seconds: u64) -> Self {
21 Self {
22 entries: RwLock::new(HashMap::new()),
23 ttl: Duration::from_secs(ttl_seconds),
24 }
25 }
26
27 pub fn cache_key(tool_name: &str, args: &serde_json::Value) -> String {
29 let mut hasher = DefaultHasher::new();
30 tool_name.hash(&mut hasher);
31 args.to_string().hash(&mut hasher);
32 format!("tool:{}:{:x}", tool_name, hasher.finish())
33 }
34
35 pub fn get(&self, tool_name: &str, args: &serde_json::Value) -> Option<serde_json::Value> {
37 let key = Self::cache_key(tool_name, args);
38 let entries = self.entries.read().unwrap();
39 if let Some(entry) = entries.get(&key) {
40 if entry.created_at.elapsed() < self.ttl {
41 return Some(entry.value.clone());
42 }
43 }
44 None
45 }
46
47 pub fn set(&self, tool_name: &str, args: &serde_json::Value, value: &serde_json::Value) {
49 let key = Self::cache_key(tool_name, args);
50 let mut entries = self.entries.write().unwrap();
51 entries.insert(
52 key,
53 CacheEntry {
54 value: value.clone(),
55 created_at: Instant::now(),
56 },
57 );
58 }
59
60 pub fn evict_expired(&self) {
62 let mut entries = self.entries.write().unwrap();
63 entries.retain(|_, e| e.created_at.elapsed() < self.ttl);
64 }
65
66 pub fn clear(&self) {
68 self.entries.write().unwrap().clear();
69 }
70
71 pub fn len(&self) -> usize {
73 self.entries.read().unwrap().len()
74 }
75
76 pub fn is_empty(&self) -> bool {
78 self.len() == 0
79 }
80}