2023-06-07 20:48:55 +03:00
|
|
|
use crate::{KQCacheWithTTL, PlaceholderGuardWithTTL};
|
2023-05-15 20:48:59 +03:00
|
|
|
use quick_cache::{DefaultHashBuilder, UnitWeighter, Weighter};
|
2023-06-07 20:48:55 +03:00
|
|
|
use serde::{Serialize, Serializer};
|
2023-05-15 20:48:59 +03:00
|
|
|
use std::{
|
2023-05-30 03:19:05 +03:00
|
|
|
fmt::Debug,
|
2023-05-15 20:48:59 +03:00
|
|
|
future::Future,
|
|
|
|
hash::{BuildHasher, Hash},
|
2023-05-30 01:48:22 +03:00
|
|
|
num::NonZeroU32,
|
2023-05-18 23:34:22 +03:00
|
|
|
sync::Arc,
|
2023-05-15 20:48:59 +03:00
|
|
|
time::Duration,
|
|
|
|
};
|
|
|
|
|
2023-05-18 23:34:22 +03:00
|
|
|
pub struct CacheWithTTL<Key, Val, We = UnitWeighter, B = DefaultHashBuilder>(
|
|
|
|
KQCacheWithTTL<Key, (), Val, We, B>,
|
|
|
|
);
|
2023-05-15 20:48:59 +03:00
|
|
|
|
2023-05-30 03:19:05 +03:00
|
|
|
impl<
|
|
|
|
Key: Clone + Debug + Eq + Hash + Send + Sync + 'static,
|
|
|
|
Val: Clone + Send + Sync + 'static,
|
|
|
|
> CacheWithTTL<Key, Val, UnitWeighter, DefaultHashBuilder>
|
2023-05-15 20:48:59 +03:00
|
|
|
{
|
2023-05-30 03:19:05 +03:00
|
|
|
pub async fn new(name: &'static str, capacity: usize, ttl: Duration) -> Self {
|
2023-05-30 01:48:22 +03:00
|
|
|
Self::new_with_options(
|
2023-05-30 03:19:05 +03:00
|
|
|
name,
|
2023-05-18 23:34:22 +03:00
|
|
|
capacity,
|
2023-05-30 01:48:22 +03:00
|
|
|
1.try_into().unwrap(),
|
2023-05-18 23:34:22 +03:00
|
|
|
capacity as u64,
|
2023-05-15 20:48:59 +03:00
|
|
|
UnitWeighter,
|
|
|
|
DefaultHashBuilder::default(),
|
|
|
|
ttl,
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
}
|
2023-05-18 23:34:22 +03:00
|
|
|
|
2023-05-30 03:19:05 +03:00
|
|
|
pub async fn arc_with_capacity(
|
|
|
|
name: &'static str,
|
|
|
|
capacity: usize,
|
|
|
|
ttl: Duration,
|
|
|
|
) -> Arc<Self> {
|
|
|
|
let x = Self::new(name, capacity, ttl).await;
|
2023-05-18 23:34:22 +03:00
|
|
|
|
|
|
|
Arc::new(x)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<
|
2023-05-30 03:19:05 +03:00
|
|
|
Key: Clone + Debug + Eq + Hash + Send + Sync + 'static,
|
2023-05-18 23:34:22 +03:00
|
|
|
Val: Clone + Send + Sync + 'static,
|
|
|
|
We: Weighter<Key, (), Val> + Clone + Send + Sync + 'static,
|
|
|
|
B: BuildHasher + Clone + Default + Send + Sync + 'static,
|
|
|
|
> CacheWithTTL<Key, Val, We, B>
|
|
|
|
{
|
|
|
|
pub async fn new_with_weights(
|
2023-05-30 03:19:05 +03:00
|
|
|
name: &'static str,
|
2023-05-18 23:34:22 +03:00
|
|
|
estimated_items_capacity: usize,
|
2023-05-30 01:48:22 +03:00
|
|
|
max_item_weigth: NonZeroU32,
|
2023-05-18 23:34:22 +03:00
|
|
|
weight_capacity: u64,
|
|
|
|
weighter: We,
|
|
|
|
ttl: Duration,
|
|
|
|
) -> Self {
|
2023-05-30 03:19:05 +03:00
|
|
|
let max_item_weight = max_item_weigth.min((weight_capacity as u32).try_into().unwrap());
|
2023-05-30 01:48:22 +03:00
|
|
|
|
|
|
|
let inner = KQCacheWithTTL::new_with_options(
|
2023-05-30 03:19:05 +03:00
|
|
|
name,
|
2023-05-18 23:34:22 +03:00
|
|
|
estimated_items_capacity,
|
2023-05-30 03:19:05 +03:00
|
|
|
max_item_weight,
|
2023-05-18 23:34:22 +03:00
|
|
|
weight_capacity,
|
|
|
|
weighter,
|
|
|
|
B::default(),
|
|
|
|
ttl,
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
Self(inner)
|
|
|
|
}
|
2023-05-15 20:48:59 +03:00
|
|
|
|
2023-05-30 01:48:22 +03:00
|
|
|
pub async fn new_with_options(
|
2023-05-30 03:19:05 +03:00
|
|
|
name: &'static str,
|
2023-05-15 20:48:59 +03:00
|
|
|
estimated_items_capacity: usize,
|
2023-05-30 01:48:22 +03:00
|
|
|
max_item_weight: NonZeroU32,
|
2023-05-15 20:48:59 +03:00
|
|
|
weight_capacity: u64,
|
|
|
|
weighter: We,
|
|
|
|
hash_builder: B,
|
|
|
|
ttl: Duration,
|
|
|
|
) -> Self {
|
2023-05-30 01:48:22 +03:00
|
|
|
let inner = KQCacheWithTTL::new_with_options(
|
2023-05-30 03:19:05 +03:00
|
|
|
name,
|
2023-05-15 20:48:59 +03:00
|
|
|
estimated_items_capacity,
|
2023-05-30 01:48:22 +03:00
|
|
|
max_item_weight,
|
2023-05-15 20:48:59 +03:00
|
|
|
weight_capacity,
|
|
|
|
weighter,
|
|
|
|
hash_builder,
|
|
|
|
ttl,
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
Self(inner)
|
|
|
|
}
|
|
|
|
|
2023-05-18 23:34:22 +03:00
|
|
|
#[inline]
|
|
|
|
pub fn get(&self, key: &Key) -> Option<Val> {
|
|
|
|
self.0.get(key, &())
|
|
|
|
}
|
|
|
|
|
2023-05-15 20:48:59 +03:00
|
|
|
#[inline]
|
2023-05-30 01:48:22 +03:00
|
|
|
pub async fn get_or_insert_async<Fut>(&self, key: &Key, f: Fut) -> Val
|
2023-05-15 20:48:59 +03:00
|
|
|
where
|
2023-05-30 01:48:22 +03:00
|
|
|
Fut: Future<Output = Val>,
|
2023-05-15 20:48:59 +03:00
|
|
|
{
|
|
|
|
self.0.get_or_insert_async(key, &(), f).await
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub async fn get_value_or_guard_async(
|
|
|
|
&self,
|
|
|
|
key: Key,
|
|
|
|
) -> Result<Val, PlaceholderGuardWithTTL<'_, Key, (), Val, We, B>> {
|
|
|
|
self.0.get_value_or_guard_async(key, ()).await
|
|
|
|
}
|
|
|
|
|
2023-06-07 20:48:55 +03:00
|
|
|
#[inline]
|
|
|
|
pub fn peek(&self, key: &Key) -> Option<Val> {
|
|
|
|
self.0.peek(key, &())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn remove(&self, key: &Key) -> bool {
|
|
|
|
self.0.remove(key, &())
|
|
|
|
}
|
|
|
|
|
2023-05-30 01:48:22 +03:00
|
|
|
/// if the item was too large to insert, it is returned with the error
|
2023-05-30 03:19:05 +03:00
|
|
|
/// IMPORTANT! Inserting the same key multiple times does NOT reset the TTL!
|
2023-05-15 20:48:59 +03:00
|
|
|
#[inline]
|
2023-05-30 01:48:22 +03:00
|
|
|
pub fn try_insert(&self, key: Key, val: Val) -> Result<(), (Key, Val)> {
|
|
|
|
self.0.try_insert(key, (), val).map_err(|(k, _q, v)| (k, v))
|
2023-05-15 20:48:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2023-06-07 20:48:55 +03:00
|
|
|
pub async fn try_get_or_insert_async<E, Fut>(&self, key: &Key, f: Fut) -> Result<Val, E>
|
|
|
|
where
|
|
|
|
Fut: Future<Output = Result<Val, E>>,
|
|
|
|
{
|
|
|
|
self.0.try_get_or_insert_async(key, &(), f).await
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<
|
|
|
|
Key: Clone + Debug + Eq + Hash + Send + Sync + 'static,
|
|
|
|
Val: Clone + Send + Sync + 'static,
|
|
|
|
We: Weighter<Key, (), Val> + Clone + Send + Sync + 'static,
|
|
|
|
B: BuildHasher + Clone + Send + Sync + 'static,
|
|
|
|
> Serialize for CacheWithTTL<Key, Val, We, B>
|
|
|
|
{
|
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
|
|
where
|
|
|
|
S: Serializer,
|
|
|
|
{
|
|
|
|
self.0.serialize(serializer)
|
2023-05-15 20:48:59 +03:00
|
|
|
}
|
|
|
|
}
|