1mod config;
7mod stats;
8mod storage;
9
10pub use config::CacheConfig;
11#[allow(unused_imports)]
12pub use config::CacheOptions;
13pub use stats::CacheStats;
14pub use storage::SchemaCache;
15#[allow(unused_imports)]
16pub use storage::{CacheEntry, CacheStorage};
17
18use anyhow::Result;
19use serde_json::Value;
20use std::sync::Arc;
21
22pub const DEFAULT_CACHE_TTL: u64 = 86400;
24
25pub const DEFAULT_CACHE_DIR: &str = ".uxc/cache/schemas";
27
28#[derive(Debug, Clone)]
30pub enum CacheResult {
31 Hit(Value),
33 Miss,
35 Bypassed,
37}
38
39impl CacheResult {
40 #[allow(dead_code)]
41 pub fn is_hit(&self) -> bool {
42 matches!(self, CacheResult::Hit(_))
43 }
44
45 #[allow(dead_code)]
46 pub fn is_miss(&self) -> bool {
47 matches!(self, CacheResult::Miss)
48 }
49
50 #[allow(dead_code)]
51 pub fn is_bypassed(&self) -> bool {
52 matches!(self, CacheResult::Bypassed)
53 }
54}
55
56pub trait Cache: Send + Sync {
61 fn get(&self, url: &str) -> Result<CacheResult>;
67
68 fn put(&self, url: &str, schema: &Value) -> Result<()>;
73
74 fn invalidate(&self, url: &str) -> Result<()>;
76
77 fn clear(&self) -> Result<()>;
79
80 fn stats(&self) -> Result<CacheStats>;
82
83 #[allow(dead_code)]
85 fn is_enabled(&self) -> bool;
86}
87
88pub fn create_cache(config: CacheConfig) -> Result<Arc<dyn Cache>> {
90 Ok(Arc::new(SchemaCache::new(config)?))
91}
92
93#[allow(dead_code)]
95pub fn create_default_cache() -> Result<Arc<dyn Cache>> {
96 Ok(Arc::new(SchemaCache::with_default_config()?))
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn test_cache_result() {
105 let hit = CacheResult::Hit(serde_json::json!( {"test": "data"} ));
106 assert!(hit.is_hit());
107 assert!(!hit.is_miss());
108 assert!(!hit.is_bypassed());
109
110 let miss = CacheResult::Miss;
111 assert!(!miss.is_hit());
112 assert!(miss.is_miss());
113 assert!(!miss.is_bypassed());
114
115 let bypassed = CacheResult::Bypassed;
116 assert!(!bypassed.is_hit());
117 assert!(!bypassed.is_miss());
118 assert!(bypassed.is_bypassed());
119 }
120}