use std::collections::BTreeSet;
use hydracache::HydraCache;
use hydracache_core::CacheCodec;
use crate::CacheEntity;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct InvalidationPlan {
keys: BTreeSet<String>,
tags: BTreeSet<String>,
}
impl InvalidationPlan {
pub fn new() -> Self {
Self::default()
}
pub fn key(mut self, key: impl Into<String>) -> Self {
self.keys.insert(key.into());
self
}
pub fn keys<I, S>(mut self, keys: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.keys.extend(keys.into_iter().map(Into::into));
self
}
pub fn tag(mut self, tag: impl Into<String>) -> Self {
self.tags.insert(tag.into());
self
}
pub fn tags<I, S>(mut self, tags: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.tags.extend(tags.into_iter().map(Into::into));
self
}
pub fn entity<E>(mut self, id: E::Id) -> Self
where
E: CacheEntity,
{
self.tags.insert(E::entity_tag_for(&id));
self
}
pub fn collection<E>(mut self) -> Self
where
E: CacheEntity,
{
if let Some(tag) = E::collection_tag() {
self.tags.insert(tag);
}
self
}
pub fn cache_entity<E>(self, id: E::Id) -> Self
where
E: CacheEntity,
{
self.entity::<E>(id).collection::<E>()
}
pub fn is_empty(&self) -> bool {
self.keys.is_empty() && self.tags.is_empty()
}
pub fn key_count(&self) -> usize {
self.keys.len()
}
pub fn tag_count(&self) -> usize {
self.tags.len()
}
pub fn key_values(&self) -> impl Iterator<Item = &str> {
self.keys.iter().map(String::as_str)
}
pub fn tag_values(&self) -> impl Iterator<Item = &str> {
self.tags.iter().map(String::as_str)
}
pub async fn execute<C>(
self,
cache: &HydraCache<C>,
) -> hydracache::CacheResult<InvalidationReport>
where
C: CacheCodec,
{
let key_count = self.keys.len();
let tag_count = self.tags.len();
let mut keys_removed = 0;
let mut tags_removed = 0;
for key in self.keys {
if cache.remove(&key).await? {
keys_removed += 1;
}
}
for tag in self.tags {
tags_removed += cache.invalidate_tag(&tag).await?;
}
Ok(InvalidationReport {
key_count,
tag_count,
keys_removed,
tags_removed,
})
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct InvalidationReport {
pub key_count: usize,
pub tag_count: usize,
pub keys_removed: u64,
pub tags_removed: u64,
}
impl InvalidationReport {
pub fn removed_entries(self) -> u64 {
self.keys_removed + self.tags_removed
}
}