use std::any::{Any, TypeId};
use std::collections::HashMap;
#[derive(Default)]
pub struct DbCache {
entries: HashMap<(TypeId, String), Box<dyn Any + Send + Sync>>,
}
impl DbCache {
pub fn new() -> Self {
Self {
entries: HashMap::new(),
}
}
pub fn store<T: Send + Sync + 'static>(
&mut self,
type_id: TypeId,
key: impl Into<String>,
entity: T,
) {
self.entries.insert((type_id, key.into()), Box::new(entity));
}
pub fn get<T: 'static>(&self, type_id: TypeId, key: &str) -> Option<&T> {
self.entries
.get(&(type_id, key.to_string()))
.and_then(|boxed| boxed.downcast_ref::<T>())
}
pub fn remove(&mut self, type_id: TypeId, key: &str) {
self.entries.remove(&(type_id, key.to_string()));
}
pub fn clear_type(&mut self, type_id: TypeId) {
self.entries.retain(|(tid, _), _| *tid != type_id);
}
pub fn clear_all(&mut self) {
self.entries.clear();
}
pub fn serialize_key(key_values: &[&str]) -> String {
key_values.join("|")
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn invalidate_type_keys<I: IntoIterator<Item = String>>(
&mut self,
type_id: TypeId,
keys: I,
) {
for key in keys {
self.remove(type_id, &key);
}
}
}
impl std::fmt::Debug for DbCache {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DbCache")
.field("entries", &self.entries.len())
.finish()
}
}
pub fn compute_cache_key(key_values: &HashMap<String, crate::provider::DbValue>) -> String {
let mut parts: Vec<String> = key_values
.iter()
.map(|(_, v)| format!("{}", v))
.collect();
parts.sort(); parts.join("|")
}