yewlish_fetch_utils/
cache.rs1use js_sys::Date;
2use std::collections::hash_map::Iter;
3
4#[derive(Default, Clone, PartialEq)]
5pub enum CachePolicy {
6 #[default]
7 StaleWhileRevalidate,
8 CacheThenNetwork,
9 NetworkOnly,
10 CacheOnly,
11}
12
13#[derive(Default, Clone, PartialEq)]
14pub struct CacheOptions {
15 pub policy: Option<CachePolicy>,
16 pub max_age: Option<f64>,
17}
18
19#[derive(Clone, Debug, PartialEq)]
20pub struct CacheEntry {
21 pub timestamp: f64,
22 pub data: serde_json::Value,
23}
24
25pub struct Cache {
26 entries: std::collections::HashMap<String, CacheEntry>,
27 policy: CachePolicy,
28 max_age: f64,
29}
30
31impl Default for Cache {
32 fn default() -> Self {
33 Self::new(CacheOptions::default())
34 }
35}
36
37pub trait Cacheable {
38 fn policy(&self) -> &CachePolicy;
39 fn max_age(&self) -> f64;
40 fn set(&mut self, key: &str, value: &serde_json::Value, max_age: Option<f64>);
41 fn get(&self, key: &str) -> Option<&CacheEntry>;
42 fn iter(&self) -> Iter<String, CacheEntry>;
43 fn remove(&mut self, key: &str);
44 fn clear(&mut self);
45}
46
47const CACHE_MAX_AGE: f64 = 10.0 * 60.0 * 1000.0; impl Cache {
50 fn new(options: CacheOptions) -> Self {
51 Self {
52 entries: std::collections::HashMap::new(),
53 policy: options.policy.unwrap_or_default(),
54 max_age: options.max_age.unwrap_or(CACHE_MAX_AGE),
55 }
56 }
57}
58
59impl Cacheable for Cache {
60 fn policy(&self) -> &CachePolicy {
61 &self.policy
62 }
63
64 fn max_age(&self) -> f64 {
65 self.max_age
66 }
67
68 fn set(&mut self, key: &str, value: &serde_json::Value, max_age: Option<f64>) {
69 self.entries.insert(
70 key.to_string(),
71 CacheEntry {
72 timestamp: Date::now() + max_age.unwrap_or(self.max_age),
73 data: value.clone(),
74 },
75 );
76 }
77
78 fn get(&self, key: &str) -> Option<&CacheEntry> {
79 if let Some(cache_entry) = self.entries.get(key) {
80 if cache_entry.timestamp > js_sys::Date::now() {
81 return Some(cache_entry);
82 }
83 }
84
85 None
86 }
87
88 #[must_use]
89 fn iter(&self) -> Iter<String, CacheEntry> {
90 self.entries.iter()
91 }
92
93 fn remove(&mut self, key: &str) {
94 self.entries.remove(key);
95 }
96
97 fn clear(&mut self) {
98 self.entries.clear();
99 }
100}