use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use tokio::sync::Mutex;
use crate::{cache_events::CacheEventSubscriber, common::{AOFRecord, CacheEntry, Operation}, config::{AsyncCacheConfig, CacheSyncConfig}, eviction_policies::common::EvictionPolicy};
pub struct Cache<K, V>
where
K: Eq + std::hash::Hash + Clone ,
{
max_size: usize,
cache: HashMap<K, CacheEntry<V>>,
eviction_policy: Box<dyn EvictionPolicy<K> + Send>,
}
impl<K, V> Cache<K, V>
where
K: Eq + std::hash::Hash + Clone + std::fmt::Debug + Send + Sync + 'static,
{
pub fn new(config: CacheSyncConfig<K>) -> Self {
let max_size = config.get_config().max_size;
let policy_type = config.get_policy_type();
Cache {
cache: HashMap::new(),
max_size,
eviction_policy: policy_type.create_policy()
}
}
}
impl<K, V> Cache<K, V>
where
K: Eq + std::hash::Hash + Clone + std::fmt::Debug
{
pub fn get(&mut self, key: &K) -> Option<&V>
{
self.eviction_policy.on_get(key);
self.cache.get(key).map(|x| &x.value)
}
pub fn get_mut(&mut self, key: &K) -> Option<&mut V>
{
self.eviction_policy.on_get(key);
self.cache.get_mut(key).map(|x| &mut x.value)
}
pub fn put(&mut self, key: K, value: V) {
if self.cache.len() >= self.max_size && !self.contains_key(&key){
if let Some(evicted) = self.eviction_policy.evict() {
self.cache.remove(&evicted);
}
}
match self.cache.get_mut(&key) {
Some(v) => {
v.value = value;
},
None => {
self.cache.insert(key.clone(), CacheEntry::new(value));
}
};
self.eviction_policy.on_set(key);
}
pub fn remove(&mut self, key: &K) {
self.cache.remove(key);
self.eviction_policy.remove(key.clone());
}
pub fn contains_key(&self, key: &K) -> bool {
return self.cache.contains_key(&key);
}
pub fn size(&self) -> usize {
return self.cache.len();
}
fn get_raw(&mut self, key: &K) -> Option<*const V> {
self.get(key).map(|x| x as *const V)
}
}
pub struct AsyncCache<K, V>
where
for<'de> K: Eq + std::hash::Hash + Clone + Deserialize<'de> + Serialize + Send + Sync,
for<'de> V: Deserialize<'de> + Serialize + Send + Sync,
{
cache: Mutex<Cache<K, V>>,
persist_read_ops: Option<bool>,
subscriber_manager: CacheEventSubscriber<K, V>
}
impl<K, V> AsyncCache <K, V>
where
for<'de> K: Eq + std::hash::Hash + Clone + std::fmt::Debug + Send + Sync + Deserialize<'de> + Serialize + 'static,
for<'de> V: Clone + Deserialize<'de> + Serialize + Send + Sync + 'static
{
pub async fn new(config: AsyncCacheConfig<K>) -> Self {
let instance = Self {
persist_read_ops: config.persist_read_ops(),
subscriber_manager: match config.get_aof_config() {
Some(v) => CacheEventSubscriber::new(Some(v.0), Some(v.1), v.2).await,
None => CacheEventSubscriber::new(None, None, None).await
},
cache: Mutex::new(Cache::new(config.get_sync_config()))
};
let mut gaurd = instance.cache.lock().await;
if let Ok(mut iter) = instance.subscriber_manager.into_iter().await {
while let Ok(Some(record)) = iter.next().await {
match record.operation {
Operation::Get => {
let _ = gaurd.get(&record.key);
},
Operation::Put => gaurd.put(record.key, record.value.unwrap()),
Operation::Remove => gaurd.remove(&record.key)
}
}
}
drop(gaurd);
instance
}
pub async fn get(&self, key: &K) -> Option<V>
{
let mut guard = self.cache.lock().await;
let value = guard.get(key).cloned();
if self.persist_read_ops.as_ref().is_some_and(|x| x.clone()) {
self.subscriber_manager.on_event(AOFRecord {
key: key.clone(),
value: None,
operation: crate::common::Operation::Get
}).await;
};
drop(guard);
value
}
pub async fn get_ref(&self, key: &K) -> Option<&V>
{
let mut gaurd = self.cache.lock().await;
let val = gaurd.get_raw(key).map(|x| unsafe{x.as_ref()}).flatten();
if self.persist_read_ops.as_ref().is_some_and(|x| x.clone()) {
self.subscriber_manager.on_event(AOFRecord {
key: key.clone(),
value: None,
operation: crate::common::Operation::Get
}).await;
};
drop(gaurd);
val
}
pub async fn put(&self, key: K, value: V) {
let mut gaurd = self.cache.lock().await;
gaurd.put(key.clone(), value.clone());
self.subscriber_manager.on_event(AOFRecord {
key: key,
value: Some(value),
operation: crate::common::Operation::Put
}).await;
drop(gaurd);
}
pub async fn remove(&self, key: &K) {
let mut gaurd = self.cache.lock().await;
gaurd.remove(key);
self.subscriber_manager.on_event(AOFRecord {
key: key.clone(),
value: None,
operation: crate::common::Operation::Remove
}).await;
drop(gaurd);
}
pub async fn contains_key(&self, key: &K) -> bool {
return self.cache.lock().await.contains_key(&key);
}
pub async fn size(&self) -> usize {
return self.cache.lock().await.size();
}
}