use crate::{NorthwardError, NorthwardResult};
use async_trait::async_trait;
use downcast_rs::{impl_downcast, DowncastSync};
use serde::{de::DeserializeOwned, Serialize};
use std::collections::HashMap;
#[async_trait]
pub trait ExtensionStore: DowncastSync + Send + Sync {
async fn delete(&self, key: &str) -> NorthwardResult<bool>;
async fn exists(&self, key: &str) -> NorthwardResult<bool>;
async fn keys(&self) -> NorthwardResult<Vec<String>>;
async fn clear(&self) -> NorthwardResult<u64>;
async fn len(&self) -> NorthwardResult<usize>;
async fn is_empty(&self) -> NorthwardResult<bool> {
Ok(self.len().await? == 0)
}
async fn get_raw(&self, key: &str) -> NorthwardResult<Option<serde_json::Value>>;
async fn set_raw(&self, key: &str, value: serde_json::Value) -> NorthwardResult<()>;
async fn get_many_raw(
&self,
keys: &[&str],
) -> NorthwardResult<HashMap<String, serde_json::Value>>;
}
impl_downcast!(sync ExtensionStore);
#[async_trait]
pub trait ExtensionStoreExt: ExtensionStore {
async fn get<T: DeserializeOwned>(&self, key: &str) -> NorthwardResult<Option<T>> {
match self.get_raw(key).await? {
Some(value) => {
let deserialized = serde_json::from_value(value).map_err(|e| {
NorthwardError::DeserializationError {
reason: e.to_string(),
}
})?;
Ok(Some(deserialized))
}
None => Ok(None),
}
}
async fn set<T: Serialize + Send + Sync>(&self, key: &str, value: &T) -> NorthwardResult<()> {
let json_value =
serde_json::to_value(value).map_err(|e| NorthwardError::SerializationError {
reason: e.to_string(),
})?;
self.set_raw(key, json_value).await
}
async fn get_many<T: DeserializeOwned>(
&self,
keys: &[&str],
) -> NorthwardResult<HashMap<String, T>> {
let raw_map = self.get_many_raw(keys).await?;
let mut result = HashMap::with_capacity(raw_map.len());
for (key, value) in raw_map {
let deserialized = serde_json::from_value(value).map_err(|e| {
NorthwardError::DeserializationError {
reason: format!("Failed to deserialize key '{}': {}", key, e),
}
})?;
result.insert(key, deserialized);
}
Ok(result)
}
}
impl<T: ExtensionStore + ?Sized> ExtensionStoreExt for T {}