odp-agent 0.1.1

Agent-side discovery and catalog navigation for the Offering Discovery Protocol.
Documentation
use std::{
    collections::BTreeMap,
    sync::{Arc, RwLock},
    time::{Duration, SystemTime},
};

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CacheRecord {
    pub body: Vec<u8>,
    pub etag: Option<String>,
    pub expires_at: SystemTime,
    pub final_url: String,
    pub last_modified: Option<String>,
    pub status: u16,
    pub stored_at: SystemTime,
}

pub trait Cache: Send + Sync {
    fn delete(&self, key: &str) -> Result<(), String>;
    fn get(&self, key: &str) -> Result<Option<CacheRecord>, String>;
    fn set(&self, key: String, record: CacheRecord) -> Result<(), String>;
}

#[derive(Default)]
pub struct MemoryCache {
    records: RwLock<BTreeMap<String, CacheRecord>>,
}

impl MemoryCache {
    pub fn new() -> Self {
        Self::default()
    }
}

impl Cache for MemoryCache {
    fn delete(&self, key: &str) -> Result<(), String> {
        self.records
            .write()
            .map_err(|_| "memory cache lock is poisoned".to_owned())?
            .remove(key);
        Ok(())
    }

    fn get(&self, key: &str) -> Result<Option<CacheRecord>, String> {
        Ok(self
            .records
            .read()
            .map_err(|_| "memory cache lock is poisoned".to_owned())?
            .get(key)
            .cloned())
    }

    fn set(&self, key: String, record: CacheRecord) -> Result<(), String> {
        self.records
            .write()
            .map_err(|_| "memory cache lock is poisoned".to_owned())?
            .insert(key, record);
        Ok(())
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct CacheFallbacks {
    pub collection: Duration,
    pub offering: Duration,
    pub service_document: Duration,
}

impl Default for CacheFallbacks {
    fn default() -> Self {
        Self {
            collection: Duration::from_secs(60 * 60),
            offering: Duration::from_secs(5 * 60),
            service_document: Duration::from_secs(4 * 60 * 60),
        }
    }
}

pub(crate) fn default_cache() -> Arc<dyn Cache> {
    Arc::new(MemoryCache::new())
}