1use std::{collections::HashMap, future::Future, pin::Pin, sync::Arc};
2
3type PrefetchContext = HashMap<String, serde_json::Value>;
5
6type PrefetchFn = Arc<dyn Fn(&HashMap<String, String>, &HashMap<String, String>) -> Pin<Box<dyn Future<Output = Result<serde_json::Value, String>>>> + Send + Sync>;
8
9pub struct PrefetchManager {
11 prefetch_functions: HashMap<String, PrefetchFn>,
13 prefetch_cache: HashMap<String, serde_json::Value>,
15}
16
17impl PrefetchManager {
18 pub fn new() -> Self {
20 Self { prefetch_functions: HashMap::new(), prefetch_cache: HashMap::new() }
21 }
22
23 pub fn register_prefetch<F, Fut>(&mut self, key: &str, prefetch_fn: F)
29 where
30 F: Fn(&HashMap<String, String>, &HashMap<String, String>) -> Fut + Send + Sync + 'static,
31 Fut: Future<Output = Result<serde_json::Value, String>> + Send + 'static,
32 {
33 self.prefetch_functions.insert(key.to_string(), Arc::new(move |params, query| Box::pin(prefetch_fn(params, query))));
34 }
35
36 pub async fn prefetch(&mut self, keys: &[&str], params: &HashMap<String, String>, query: &HashMap<String, String>) -> PrefetchContext {
46 let mut context = PrefetchContext::new();
47
48 for key in keys {
49 let cache_key = self.generate_cache_key(key, params, query);
51
52 if let Some(cached) = self.prefetch_cache.get(&cache_key) {
54 context.insert(key.to_string(), cached.clone());
55 continue;
56 }
57
58 if let Some(prefetch_fn) = self.prefetch_functions.get(*key) {
60 match prefetch_fn(params, query).await {
61 Ok(value) => {
62 context.insert(key.to_string(), value.clone());
63 self.prefetch_cache.insert(cache_key, value);
65 }
66 Err(err) => {
67 eprintln!("Prefetch error for {}: {}", key, err);
68 }
69 }
70 }
71 }
72
73 context
74 }
75
76 fn generate_cache_key(&self, key: &str, params: &HashMap<String, String>, query: &HashMap<String, String>) -> String {
86 let mut cache_key = key.to_string();
87
88 let mut param_pairs: Vec<String> = params.iter().map(|(k, v)| format!("{}={}", k, v)).collect();
90 param_pairs.sort();
91 for pair in param_pairs {
92 cache_key.push_str(&format!("&{}", pair));
93 }
94
95 let mut query_pairs: Vec<String> = query.iter().map(|(k, v)| format!("{}={}", k, v)).collect();
97 query_pairs.sort();
98 for pair in query_pairs {
99 cache_key.push_str(&format!("&{}", pair));
100 }
101
102 cache_key
103 }
104
105 pub fn clear_cache(&mut self) {
107 self.prefetch_cache.clear();
108 }
109}