phantom_frame/
cache.rs

1use std::collections::HashMap;
2use std::sync::Arc;
3use tokio::sync::{broadcast, RwLock};
4
5/// A trigger that can be cloned and triggered multiple times
6/// Similar to oneshot but reusable
7#[derive(Clone)]
8pub struct RefreshTrigger {
9    sender: broadcast::Sender<()>,
10}
11
12impl RefreshTrigger {
13    pub fn new() -> Self {
14        let (sender, _) = broadcast::channel(16);
15        Self { sender }
16    }
17
18    /// Trigger a cache refresh
19    pub fn trigger(&self) {
20        // Ignore errors if there are no receivers
21        let _ = self.sender.send(());
22    }
23
24    /// Subscribe to refresh events
25    pub fn subscribe(&self) -> broadcast::Receiver<()> {
26        self.sender.subscribe()
27    }
28}
29
30/// Cache storage for prerendered content
31#[derive(Clone)]
32pub struct CacheStore {
33    store: Arc<RwLock<HashMap<String, CachedResponse>>>,
34    refresh_trigger: RefreshTrigger,
35}
36
37#[derive(Clone, Debug)]
38pub struct CachedResponse {
39    pub body: Vec<u8>,
40    pub headers: HashMap<String, String>,
41    pub status: u16,
42}
43
44impl CacheStore {
45    pub fn new(refresh_trigger: RefreshTrigger) -> Self {
46        Self {
47            store: Arc::new(RwLock::new(HashMap::new())),
48            refresh_trigger,
49        }
50    }
51
52    pub async fn get(&self, key: &str) -> Option<CachedResponse> {
53        let store = self.store.read().await;
54        store.get(key).cloned()
55    }
56
57    pub async fn set(&self, key: String, response: CachedResponse) {
58        let mut store = self.store.write().await;
59        store.insert(key, response);
60    }
61
62    pub async fn clear(&self) {
63        let mut store = self.store.write().await;
64        store.clear();
65    }
66
67    pub fn refresh_trigger(&self) -> &RefreshTrigger {
68        &self.refresh_trigger
69    }
70
71    /// Get the number of cached items
72    pub async fn size(&self) -> usize {
73        let store = self.store.read().await;
74        store.len()
75    }
76}
77
78impl Default for RefreshTrigger {
79    fn default() -> Self {
80        Self::new()
81    }
82}