use std::sync::Arc;
use matrix_sdk_base::store::WellKnownResponse;
use matrix_sdk_common::{locks::Mutex, ttl::TtlValue};
use ruma::api::{
SupportedVersions,
client::discovery::{
get_authorization_server_metadata::v1::AuthorizationServerMetadata,
get_capabilities::v3::Capabilities,
},
};
use tokio::sync::Mutex as AsyncMutex;
use crate::HttpError;
pub(crate) struct ClientCaches {
pub(crate) supported_versions: Cache<SupportedVersions, Arc<HttpError>>,
pub(super) well_known: Cache<Option<WellKnownResponse>, ()>,
pub(crate) server_metadata: Cache<AuthorizationServerMetadata, ()>,
pub(crate) homeserver_capabilities: Cache<Capabilities, Arc<HttpError>>,
}
#[derive(Clone, Debug)]
pub(crate) enum CachedValue<Value> {
Cached(Value),
NotSet,
}
impl<Value> CachedValue<Value> {
pub(super) fn take(&mut self) -> Option<Value> {
let prev = std::mem::replace(self, Self::NotSet);
match prev {
Self::Cached(value) => Some(value),
Self::NotSet => None,
}
}
}
pub(crate) struct Cache<Value, Error> {
value: Mutex<CachedValue<TtlValue<Value>>>,
pub(crate) refresh_lock: AsyncMutex<Result<(), Error>>,
}
impl<Value, Error> Cache<Value, Error> {
pub(crate) fn new() -> Self {
Self::with_value(CachedValue::NotSet)
}
pub(crate) fn with_value(value: CachedValue<TtlValue<Value>>) -> Self {
Self { value: Mutex::new(value), refresh_lock: AsyncMutex::new(Ok(())) }
}
pub(crate) fn set_value(&self, value: TtlValue<Value>) {
*self.value.lock() = CachedValue::Cached(value);
}
pub(crate) fn reset(&self) {
self.value.lock().take();
}
}
impl<Value, Error> Cache<Value, Error>
where
Value: Clone,
{
pub(crate) fn value(&self) -> CachedValue<TtlValue<Value>> {
self.value.lock().clone()
}
}