use std::collections::HashMap;
use std::hash::{DefaultHasher, Hash, Hasher};
use std::sync::RwLock;
use std::time::{Duration, Instant};
#[derive(Debug)]
pub struct ToolResultCache {
entries: RwLock<HashMap<String, CacheEntry>>,
ttl: Duration,
}
#[derive(Debug, Clone)]
struct CacheEntry {
value: serde_json::Value,
created_at: Instant,
}
impl ToolResultCache {
pub fn new(ttl_seconds: u64) -> Self {
Self {
entries: RwLock::new(HashMap::new()),
ttl: Duration::from_secs(ttl_seconds),
}
}
pub fn cache_key(tool_name: &str, args: &serde_json::Value) -> String {
let mut hasher = DefaultHasher::new();
tool_name.hash(&mut hasher);
args.to_string().hash(&mut hasher);
format!("tool:{}:{:x}", tool_name, hasher.finish())
}
pub fn get(&self, tool_name: &str, args: &serde_json::Value) -> Option<serde_json::Value> {
let key = Self::cache_key(tool_name, args);
let entries = self.entries.read().unwrap();
if let Some(entry) = entries.get(&key) {
if entry.created_at.elapsed() < self.ttl {
return Some(entry.value.clone());
}
}
None
}
pub fn set(&self, tool_name: &str, args: &serde_json::Value, value: &serde_json::Value) {
let key = Self::cache_key(tool_name, args);
let mut entries = self.entries.write().unwrap();
entries.insert(
key,
CacheEntry {
value: value.clone(),
created_at: Instant::now(),
},
);
}
pub fn evict_expired(&self) {
let mut entries = self.entries.write().unwrap();
entries.retain(|_, e| e.created_at.elapsed() < self.ttl);
}
pub fn clear(&self) {
self.entries.write().unwrap().clear();
}
pub fn len(&self) -> usize {
self.entries.read().unwrap().len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}