use crate::ParsedSchema;
use indexmap::IndexMap;
use std::sync::{Arc, RwLock};
#[derive(Clone)]
pub struct ParsedSchemaCache {
cache: Arc<RwLock<IndexMap<String, Arc<ParsedSchema>>>>,
}
impl ParsedSchemaCache {
pub fn new() -> Self {
Self {
cache: Arc::new(RwLock::new(IndexMap::new())),
}
}
pub fn insert(&self, key: String, schema: Arc<ParsedSchema>) -> Option<Arc<ParsedSchema>> {
let mut cache = self.cache.write().unwrap();
cache.insert(key, schema)
}
pub fn get(&self, key: &str) -> Option<Arc<ParsedSchema>> {
let cache = self.cache.read().unwrap();
cache.get(key).cloned()
}
pub fn remove(&self, key: &str) -> Option<Arc<ParsedSchema>> {
let mut cache = self.cache.write().unwrap();
cache.shift_remove(key)
}
pub fn clear(&self) {
let mut cache = self.cache.write().unwrap();
cache.clear();
}
pub fn contains_key(&self, key: &str) -> bool {
let cache = self.cache.read().unwrap();
cache.contains_key(key)
}
pub fn len(&self) -> usize {
let cache = self.cache.read().unwrap();
cache.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn keys(&self) -> Vec<String> {
let cache = self.cache.read().unwrap();
cache.keys().cloned().collect()
}
pub fn stats(&self) -> ParsedSchemaCacheStats {
let cache = self.cache.read().unwrap();
ParsedSchemaCacheStats {
entry_count: cache.len(),
keys: cache.keys().cloned().collect(),
}
}
pub fn get_or_insert_with<F>(&self, key: &str, factory: F) -> Arc<ParsedSchema>
where
F: FnOnce() -> Arc<ParsedSchema>,
{
{
let cache = self.cache.read().unwrap();
if let Some(schema) = cache.get(key) {
return schema.clone();
}
}
let mut cache = self.cache.write().unwrap();
if let Some(schema) = cache.get(key) {
return schema.clone();
}
let schema = factory();
cache.insert(key.to_string(), schema.clone());
schema
}
pub fn insert_batch(&self, entries: Vec<(String, Arc<ParsedSchema>)>) {
let mut cache = self.cache.write().unwrap();
for (key, schema) in entries {
cache.insert(key, schema);
}
}
pub fn remove_batch(&self, keys: &[String]) -> Vec<(String, Arc<ParsedSchema>)> {
let mut cache = self.cache.write().unwrap();
let mut removed = Vec::new();
for key in keys {
if let Some(schema) = cache.shift_remove(key) {
removed.push((key.clone(), schema));
}
}
removed
}
}
impl Default for ParsedSchemaCache {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct ParsedSchemaCacheStats {
pub entry_count: usize,
pub keys: Vec<String>,
}
impl std::fmt::Display for ParsedSchemaCacheStats {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ParsedSchemaCache: {} entries", self.entry_count)?;
if !self.keys.is_empty() {
write!(f, " (keys: {})", self.keys.join(", "))?;
}
Ok(())
}
}
use once_cell::sync::Lazy;
pub static PARSED_SCHEMA_CACHE: Lazy<ParsedSchemaCache> = Lazy::new(ParsedSchemaCache::new);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cache_basic_operations() {
let cache = ParsedSchemaCache::new();
assert_eq!(cache.len(), 0);
assert!(cache.is_empty());
assert!(!cache.contains_key("test"));
assert_eq!(cache.keys().len(), 0);
}
#[test]
fn test_cache_clone() {
let cache1 = ParsedSchemaCache::new();
let cache2 = cache1.clone();
assert_eq!(cache1.len(), cache2.len());
}
}