#[cfg(feature = "database")]
use super::memory::{Memory, MemoryQuery, MemoryStats, MemoryValue};
#[cfg(feature = "database")]
use crate::RragResult;
#[cfg(feature = "database")]
use async_trait::async_trait;
#[cfg(feature = "database")]
#[derive(Debug, Clone)]
pub struct DatabaseConfig {
pub connection_string: String,
pub max_connections: u32,
pub connection_timeout_secs: u64,
pub enable_query_logging: bool,
}
#[cfg(feature = "database")]
impl Default for DatabaseConfig {
fn default() -> Self {
Self {
connection_string: "sqlite::memory:".to_string(),
max_connections: 10,
connection_timeout_secs: 30,
enable_query_logging: false,
}
}
}
#[cfg(feature = "database")]
pub struct DatabaseStorage {
config: DatabaseConfig,
fallback: super::in_memory::InMemoryStorage,
}
#[cfg(feature = "database")]
impl DatabaseStorage {
pub async fn new() -> RragResult<Self> {
Self::with_config(DatabaseConfig::default()).await
}
pub async fn with_config(config: DatabaseConfig) -> RragResult<Self> {
tracing::warn!(
"DatabaseStorage is using in-memory fallback. Full Toasty integration pending."
);
Ok(Self {
config,
fallback: super::in_memory::InMemoryStorage::new(),
})
}
}
#[cfg(feature = "database")]
#[async_trait]
impl Memory for DatabaseStorage {
fn backend_name(&self) -> &str {
"database_fallback"
}
async fn set(&self, key: &str, value: MemoryValue) -> RragResult<()> {
self.fallback.set(key, value).await
}
async fn get(&self, key: &str) -> RragResult<Option<MemoryValue>> {
self.fallback.get(key).await
}
async fn delete(&self, key: &str) -> RragResult<bool> {
self.fallback.delete(key).await
}
async fn exists(&self, key: &str) -> RragResult<bool> {
self.fallback.exists(key).await
}
async fn keys(&self, query: &MemoryQuery) -> RragResult<Vec<String>> {
self.fallback.keys(query).await
}
async fn mget(&self, keys: &[String]) -> RragResult<Vec<Option<MemoryValue>>> {
self.fallback.mget(keys).await
}
async fn mset(&self, pairs: &[(String, MemoryValue)]) -> RragResult<()> {
self.fallback.mset(pairs).await
}
async fn mdelete(&self, keys: &[String]) -> RragResult<usize> {
self.fallback.mdelete(keys).await
}
async fn clear(&self, namespace: Option<&str>) -> RragResult<()> {
self.fallback.clear(namespace).await
}
async fn count(&self, namespace: Option<&str>) -> RragResult<usize> {
self.fallback.count(namespace).await
}
async fn health_check(&self) -> RragResult<bool> {
self.fallback.health_check().await
}
async fn stats(&self) -> RragResult<MemoryStats> {
let mut stats = self.fallback.stats().await?;
stats.backend_type = format!("database_fallback ({})", self.config.connection_string);
stats.extra.insert(
"note".to_string(),
serde_json::json!("Using in-memory fallback until Toasty is fully integrated"),
);
Ok(stats)
}
}
#[cfg(not(feature = "database"))]
pub struct DatabaseStorage;
#[cfg(not(feature = "database"))]
impl DatabaseStorage {
pub async fn new() -> Result<Self, String> {
Err("Database feature not enabled. Enable with --features database".to_string())
}
}