use crate::store::{config::AdapterConfig, error::{Error as StoreError, Result as StoreResult}};
use crate::common::namespace::Namespace;
#[derive(Debug, Clone)]
pub struct CacheConfig {
pub default_namespace: Namespace,
pub default_ttl: Option<std::time::Duration>,
pub max_entries: Option<usize>,
}
impl Default for CacheConfig {
fn default() -> Self {
Self {
default_namespace: Namespace::named("default"),
default_ttl: None,
max_entries: None,
}
}
}
impl CacheConfig {
pub fn with_namespace(ns: impl Into<String>) -> Self {
Self {
default_namespace: Namespace::named(ns),
..Default::default()
}
}
}
impl AdapterConfig for CacheConfig {
fn adapter_name(&self) -> &'static str {
"cache"
}
fn validate(&self) -> StoreResult<()> {
if self.default_namespace.is_default() {
return Err(StoreError::config(
"cache default_namespace must be a named namespace",
));
}
if let Some(max) = self.max_entries
&& max == 0 {
return Err(StoreError::config("max_entries must be greater than zero if set"));
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::store::error::Error as StoreError;
#[test]
fn default_has_named_namespace() {
let c = CacheConfig::default();
assert!(!c.default_namespace.is_default());
assert_eq!(c.default_namespace.as_deref(), Some("default"));
}
#[test]
fn default_has_no_ttl() {
assert!(CacheConfig::default().default_ttl.is_none());
}
#[test]
fn default_has_no_max_entries() {
assert!(CacheConfig::default().max_entries.is_none());
}
#[test]
fn with_namespace_sets_namespace() {
let c = CacheConfig::with_namespace("embeddings");
assert_eq!(c.default_namespace.as_deref(), Some("embeddings"));
}
#[test]
fn adapter_name_is_cache() {
assert_eq!(CacheConfig::default().adapter_name(), "cache");
}
#[test]
fn validate_passes_for_valid_config() {
assert!(CacheConfig::default().validate().is_ok());
}
#[test]
fn validate_fails_for_bare_default_namespace() {
let c = CacheConfig {
default_namespace: Namespace::default_ns(),
..Default::default()
};
let err = c.validate().unwrap_err();
assert!(matches!(err, StoreError::Configuration(_)));
assert!(err.to_string().contains("named namespace"));
}
#[test]
fn validate_fails_for_zero_max_entries() {
let c = CacheConfig {
max_entries: Some(0),
..Default::default()
};
let err = c.validate().unwrap_err();
assert!(matches!(err, StoreError::Configuration(_)));
assert!(err.to_string().contains("max_entries"));
}
#[test]
fn validate_passes_with_explicit_max_entries() {
let c = CacheConfig { max_entries: Some(1000), ..Default::default() };
assert!(c.validate().is_ok());
}
#[test]
fn validate_passes_with_ttl() {
let c = CacheConfig {
default_ttl: Some(std::time::Duration::from_secs(300)),
..Default::default()
};
assert!(c.validate().is_ok());
}
}