zen_engine/loader/
cached.rs

1use ahash::{HashMap, HashMapExt};
2use std::future::Future;
3use std::sync::Arc;
4use tokio::sync::Mutex;
5
6use crate::loader::{DecisionLoader, LoaderResponse};
7use crate::model::DecisionContent;
8
9pub struct CachedLoader<Loader: DecisionLoader + 'static> {
10    loader: Arc<Loader>,
11    cache: Mutex<HashMap<String, Arc<DecisionContent>>>,
12}
13
14impl<Loader: DecisionLoader + 'static> From<Arc<Loader>> for CachedLoader<Loader> {
15    fn from(value: Arc<Loader>) -> Self {
16        Self {
17            loader: value,
18            cache: Mutex::new(HashMap::new()),
19        }
20    }
21}
22
23impl<Loader: DecisionLoader + 'static> DecisionLoader for CachedLoader<Loader> {
24    fn load<'a>(&'a self, key: &'a str) -> impl Future<Output = LoaderResponse> + 'a {
25        async move {
26            let mut cache = self.cache.lock().await;
27            if let Some(content) = cache.get(key) {
28                return Ok(content.clone());
29            }
30
31            let decision_content = self.loader.load(key).await?;
32            cache.insert(key.to_string(), decision_content.clone());
33            Ok(decision_content)
34        }
35    }
36}