use std::{fmt::Display, hash::Hash, ops::Deref};
use async_trait::async_trait;
use chrono::NaiveDateTime;
use gw2lib_model::{Endpoint, Language};
use serde::{de::DeserializeOwned, Serialize};
pub(crate) mod in_memory;
pub use in_memory::InMemoryCache;
pub use noop::NoopCache;
mod noop;
#[cfg(feature = "redis")]
mod redis;
#[cfg(feature = "redis")]
pub use self::redis::RedisCache;
#[async_trait]
pub trait Cache {
async fn insert<T, I, E, A>(
&self,
id: &I,
endpoint: &T,
expiring: NaiveDateTime,
lang: Language,
auth: &Option<A>,
) where
T: DeserializeOwned + Serialize + Clone + Send + Sync + 'static,
I: Display + Hash + Sync + 'static + ?Sized,
E: Endpoint,
A: Display + Hash + Sync + 'static;
async fn get<T, I, E, A>(&self, id: &I, lang: Language, auth: &Option<A>) -> Option<T>
where
T: DeserializeOwned + Serialize + Clone + Send + Sync + 'static,
I: Display + Hash + Sync + 'static + ?Sized,
E: Endpoint,
A: Display + Hash + Sync + 'static;
async fn cleanup(&self);
async fn wipe(&self) {
self.wipe_static().await;
self.wipe_authenticated().await;
}
async fn wipe_static(&self);
async fn wipe_authenticated(&self);
}
#[async_trait]
pub(crate) trait CleanupCache {
async fn cleanup(&self);
}
#[async_trait]
impl<T> CleanupCache for T
where
T: Cache + Send + Sync + 'static,
{
async fn cleanup(&self) {
Cache::cleanup(self).await;
}
}
#[async_trait]
impl<X, K> Cache for X
where
X: Deref<Target = K> + Sync,
K: Cache + Sync,
{
async fn insert<T, I, E, A>(
&self,
id: &I,
endpoint: &T,
expiring: NaiveDateTime,
lang: Language,
auth: &Option<A>,
) where
T: DeserializeOwned + Serialize + Clone + Send + Sync + 'static,
I: Display + Hash + Sync + 'static + ?Sized,
E: Endpoint,
A: Display + Hash + Sync + 'static,
{
self.deref()
.insert::<T, I, E, A>(id, endpoint, expiring, lang, auth)
.await
}
async fn get<T, I, E, A>(&self, id: &I, lang: Language, auth: &Option<A>) -> Option<T>
where
T: DeserializeOwned + Serialize + Clone + Send + Sync + 'static,
I: Display + Hash + Sync + 'static + ?Sized,
E: Endpoint,
A: Display + Hash + Sync + 'static,
{
self.deref().get::<T, I, E, A>(id, lang, auth).await
}
async fn cleanup(&self) {
self.deref().cleanup().await
}
async fn wipe_static(&self) {
self.deref().wipe_static().await
}
async fn wipe_authenticated(&self) {
self.deref().wipe_authenticated().await
}
}