use std::{fmt::Debug, rc::Rc};
use crate::{query::Query, QueryState};
pub trait CacheObserver {
fn process_cache_event(&self, event: CacheEvent);
}
#[derive(Clone, Debug)]
pub enum CacheEvent {
Created(CreatedQuery),
Updated(SerializedQuery),
Removed(QueryCacheKey),
ObserverAdded(ObserverAdded),
ObserverRemoved(QueryCacheKey),
}
impl CacheEvent {
pub(crate) fn created<K, V>(query: Query<K, V>) -> Self
where
K: crate::QueryKey + 'static,
V: crate::QueryValue + 'static,
{
let payload = query.into();
CacheEvent::Created(payload)
}
pub(crate) fn updated<K, V>(query: Query<K, V>) -> Self
where
K: crate::QueryKey + 'static,
V: crate::QueryValue + 'static,
{
let payload = query.into();
CacheEvent::Updated(payload)
}
pub(crate) fn removed<K>(key: &K) -> Self
where
K: crate::QueryKey + 'static,
{
CacheEvent::Removed(key.into())
}
pub(crate) fn observer_added<K, V>(key: &K, options: crate::QueryOptions<V>) -> Self
where
K: crate::QueryKey + 'static,
V: crate::QueryValue + 'static,
{
let options =
options.map_value(|v| leptos::Serializable::ser(&v).expect("Serialize Query Options"));
CacheEvent::ObserverAdded(ObserverAdded {
key: key.into(),
options,
})
}
pub(crate) fn observer_removed<K>(key: &K) -> Self
where
K: crate::QueryKey + 'static,
{
CacheEvent::ObserverRemoved(key.into())
}
}
#[derive(Clone)]
pub struct CreatedQuery {
pub key: QueryCacheKey,
pub state: QueryState<String>,
pub mark_invalid: Rc<dyn Fn() -> bool>,
}
impl Debug for CreatedQuery {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CreatedQuery")
.field("key", &self.key)
.field("state", &self.state)
.finish()
}
}
#[derive(Clone, Debug)]
pub struct SerializedQuery {
pub key: QueryCacheKey,
pub state: QueryState<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct QueryCacheKey(pub String);
#[derive(Clone, Debug)]
pub struct ObserverAdded {
pub key: QueryCacheKey,
pub options: crate::QueryOptions<String>,
}
impl<K, V> From<Query<K, V>> for CreatedQuery
where
K: crate::QueryKey + 'static,
V: crate::QueryValue + 'static,
{
fn from(query: Query<K, V>) -> Self {
let key: QueryCacheKey = query.get_key().into();
let state = query.with_state(|state| {
state.map_data(|data| leptos::Serializable::ser(data).expect("Serialize Query State"))
});
let mark_invalid = Rc::new(move || query.mark_invalid());
CreatedQuery {
key,
state,
mark_invalid,
}
}
}
impl<K, V> From<Query<K, V>> for SerializedQuery
where
K: crate::QueryKey + 'static,
V: crate::QueryValue + 'static,
{
fn from(query: Query<K, V>) -> Self {
let key: QueryCacheKey = query.get_key().into();
let state = query.with_state(|state| {
state.map_data(|data| leptos::Serializable::ser(data).expect("Serialize Query State"))
});
SerializedQuery { key, state }
}
}
impl<K> From<&K> for QueryCacheKey
where
K: crate::QueryKey + 'static,
{
fn from(key: &K) -> Self {
QueryCacheKey(make_cache_key(key))
}
}
pub(crate) fn make_cache_key<K>(key: &K) -> String
where
K: crate::QueryKey + 'static,
{
format!("{key:?}")
}