subx_cli/services/ai/
cache.rs1use crate::services::ai::{AnalysisRequest, MatchResult};
2use std::collections::HashMap;
3use std::collections::hash_map::DefaultHasher;
4use std::hash::{Hash, Hasher};
5use std::time::{Duration, SystemTime};
6use tokio::sync::RwLock;
7
8pub struct AICache {
10 cache: RwLock<HashMap<String, CacheEntry>>,
11 ttl: Duration,
12}
13
14struct CacheEntry {
15 data: MatchResult,
16 created_at: SystemTime,
17}
18
19impl AICache {
20 pub fn new(ttl: Duration) -> Self {
22 Self {
23 cache: RwLock::new(HashMap::new()),
24 ttl,
25 }
26 }
27
28 pub async fn get(&self, key: &str) -> Option<MatchResult> {
30 let cache = self.cache.read().await;
31
32 if let Some(entry) = cache.get(key) {
33 if entry.created_at.elapsed().unwrap_or(Duration::MAX) < self.ttl {
34 return Some(entry.data.clone());
35 }
36 }
37 None
38 }
39
40 pub async fn set(&self, key: String, data: MatchResult) {
42 let mut cache = self.cache.write().await;
43 cache.insert(
44 key,
45 CacheEntry {
46 data,
47 created_at: SystemTime::now(),
48 },
49 );
50 }
51
52 pub fn generate_key(request: &AnalysisRequest) -> String {
54 let mut hasher = DefaultHasher::new();
55 request.video_files.hash(&mut hasher);
56 request.subtitle_files.hash(&mut hasher);
57 format!("{:x}", hasher.finish())
58 }
59}