use crate::error::CacheResult;
use crate::traits::CacheStore;
use serde::{Serialize, de::DeserializeOwned};
use std::time::Duration;
pub async fn get<S: CacheStore, T: DeserializeOwned>(
store: &S,
key: &str,
) -> CacheResult<Option<T>> {
if let Some(json) = store.get_json(key).await? {
let value: T = serde_json::from_str(&json)
.map_err(|e| crate::error::CacheError::Deserialization(e.to_string()))?;
Ok(Some(value))
} else {
Ok(None)
}
}
pub async fn set<S: CacheStore, T: Serialize>(
store: &S,
key: &str,
value: &T,
ttl: Option<Duration>,
) -> CacheResult<()> {
let json = serde_json::to_string(value)
.map_err(|e| crate::error::CacheError::Serialization(e.to_string()))?;
store.set_json(key, json, ttl).await
}
pub async fn remember<S: CacheStore, T, F, Fut>(
store: &S,
key: &str,
ttl: Duration,
factory: F,
) -> CacheResult<T>
where
T: Serialize + DeserializeOwned,
F: FnOnce() -> Fut,
Fut: std::future::Future<Output = CacheResult<T>>,
{
if let Some(value) = get(store, key).await? {
return Ok(value);
}
let value = factory().await?;
set(store, key, &value, Some(ttl)).await?;
Ok(value)
}
pub async fn remember_forever<S: CacheStore, T, F, Fut>(
store: &S,
key: &str,
factory: F,
) -> CacheResult<T>
where
T: Serialize + DeserializeOwned,
F: FnOnce() -> Fut,
Fut: std::future::Future<Output = CacheResult<T>>,
{
if let Some(value) = get(store, key).await? {
return Ok(value);
}
let value = factory().await?;
set(store, key, &value, None).await?;
Ok(value)
}