use crate::entry::CacheEntry;
use crate::error::Result;
use async_trait::async_trait;
use serde::{Serialize, de::DeserializeOwned};
use std::collections::HashMap;
use std::hash::Hash;
pub type EntryMap<K, V, M> = HashMap<K, Vec<CacheEntry<K, V, M>>>;
#[async_trait]
pub trait StorageBackend: Send + Sync + 'static {
type Key: Serialize + DeserializeOwned + Hash + Eq + Clone + Send + Sync;
type Value: Serialize + DeserializeOwned + Clone + Send + Sync;
type Metadata: Serialize + DeserializeOwned + Clone + Send + Sync;
async fn save(&self, entries: &EntryMap<Self::Key, Self::Value, Self::Metadata>) -> Result<()>;
async fn load(&self) -> Result<EntryMap<Self::Key, Self::Value, Self::Metadata>>;
async fn remove(&self, key: &Self::Key) -> Result<()>;
async fn clear(&self) -> Result<()>;
async fn contains(&self, key: &Self::Key) -> Result<bool> {
let entries = self.load().await?;
Ok(entries.contains_key(key))
}
async fn size_bytes(&self) -> Result<u64>;
async fn compact(&self) -> Result<()> {
Ok(()) }
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_default_storage_methods() {
use crate::test_utils::TestBackend;
use std::collections::HashMap;
let backend = TestBackend::default();
let mut map = HashMap::new();
map.insert(
"a".to_string(),
vec![CacheEntry::new("a".to_string(), "v".to_string())],
);
backend.save(&map).await.unwrap();
assert!(backend.contains(&"a".to_string()).await.unwrap());
assert!(!backend.contains(&"b".to_string()).await.unwrap());
assert!(backend.size_bytes().await.unwrap() > 0);
backend.compact().await.unwrap();
}
}