1use std::{
2 collections::BTreeMap,
3 sync::{Arc, RwLock},
4 time::{Duration, SystemTime},
5};
6
7#[derive(Clone, Debug, Eq, PartialEq)]
8pub struct CacheRecord {
9 pub body: Vec<u8>,
10 pub etag: Option<String>,
11 pub expires_at: SystemTime,
12 pub final_url: String,
13 pub last_modified: Option<String>,
14 pub status: u16,
15 pub stored_at: SystemTime,
16}
17
18pub trait Cache: Send + Sync {
19 fn delete(&self, key: &str) -> Result<(), String>;
20 fn get(&self, key: &str) -> Result<Option<CacheRecord>, String>;
21 fn set(&self, key: String, record: CacheRecord) -> Result<(), String>;
22}
23
24#[derive(Default)]
25pub struct MemoryCache {
26 records: RwLock<BTreeMap<String, CacheRecord>>,
27}
28
29impl MemoryCache {
30 pub fn new() -> Self {
31 Self::default()
32 }
33}
34
35impl Cache for MemoryCache {
36 fn delete(&self, key: &str) -> Result<(), String> {
37 self.records
38 .write()
39 .map_err(|_| "memory cache lock is poisoned".to_owned())?
40 .remove(key);
41 Ok(())
42 }
43
44 fn get(&self, key: &str) -> Result<Option<CacheRecord>, String> {
45 Ok(self
46 .records
47 .read()
48 .map_err(|_| "memory cache lock is poisoned".to_owned())?
49 .get(key)
50 .cloned())
51 }
52
53 fn set(&self, key: String, record: CacheRecord) -> Result<(), String> {
54 self.records
55 .write()
56 .map_err(|_| "memory cache lock is poisoned".to_owned())?
57 .insert(key, record);
58 Ok(())
59 }
60}
61
62#[derive(Clone, Copy, Debug, Eq, PartialEq)]
63pub struct CacheFallbacks {
64 pub collection: Duration,
65 pub offering: Duration,
66 pub service_document: Duration,
67}
68
69impl Default for CacheFallbacks {
70 fn default() -> Self {
71 Self {
72 collection: Duration::from_secs(60 * 60),
73 offering: Duration::from_secs(5 * 60),
74 service_document: Duration::from_secs(4 * 60 * 60),
75 }
76 }
77}
78
79pub(crate) fn default_cache() -> Arc<dyn Cache> {
80 Arc::new(MemoryCache::new())
81}