use std::path::{Path, PathBuf};
use std::time::Duration;
pub use linkrs_config::SyncMode;
#[derive(Debug, Clone)]
pub struct DatabaseConfig {
pub path: Option<PathBuf>,
pub cache_size_mb: usize,
pub default_timeout: Duration,
pub enable_wal: bool,
pub sync_mode: SyncMode,
pub read_only: bool,
pub create_if_missing: bool,
pub vector: VectorConfig,
}
#[derive(Debug, Clone, Default)]
pub enum EmbeddedVectorEngine {
#[default]
Local,
#[cfg(feature = "vector-qdrant")]
Qdrant(Box<vector_client::VectorClientConfig>),
}
#[derive(Debug, Clone)]
pub struct VectorConfig {
pub enabled: bool,
pub engine: EmbeddedVectorEngine,
pub local_data_dir: Option<PathBuf>,
}
impl Default for VectorConfig {
fn default() -> Self {
Self {
enabled: true,
engine: EmbeddedVectorEngine::Local,
local_data_dir: None,
}
}
}
impl DatabaseConfig {
pub fn memory() -> Self {
Self {
path: None,
cache_size_mb: 64,
default_timeout: Duration::from_secs(30),
enable_wal: true,
sync_mode: SyncMode::Normal,
read_only: false,
create_if_missing: true,
vector: VectorConfig::default(),
}
}
pub fn file(path: impl AsRef<Path>) -> Self {
Self {
path: Some(path.as_ref().to_path_buf()),
cache_size_mb: 64,
default_timeout: Duration::from_secs(30),
enable_wal: true,
sync_mode: SyncMode::Normal,
read_only: false,
create_if_missing: true,
vector: VectorConfig::default(),
}
}
pub fn new(path: impl AsRef<Path>) -> Self {
Self::file(path)
}
pub fn with_cache_size(mut self, size_mb: usize) -> Self {
self.cache_size_mb = size_mb;
self
}
pub fn with_timeout(mut self, timeout: Duration) -> Self {
self.default_timeout = timeout;
self
}
pub fn with_wal(mut self, enable: bool) -> Self {
self.enable_wal = enable;
self
}
pub fn with_sync_mode(mut self, mode: SyncMode) -> Self {
self.sync_mode = mode;
self
}
pub fn with_read_only(mut self, read_only: bool) -> Self {
self.read_only = read_only;
self
}
pub fn with_create_if_missing(mut self, create: bool) -> Self {
self.create_if_missing = create;
self
}
pub fn with_vector_enabled(mut self, enabled: bool) -> Self {
self.vector.enabled = enabled;
self
}
pub fn with_vector_local_dir(mut self, dir: impl Into<PathBuf>) -> Self {
self.vector.local_data_dir = Some(dir.into());
self
}
#[cfg(feature = "vector-qdrant")]
pub fn with_vector_qdrant(mut self, config: vector_client::VectorClientConfig) -> Self {
self.vector.engine = EmbeddedVectorEngine::Qdrant(Box::new(config));
self
}
pub fn is_memory(&self) -> bool {
self.path.is_none()
}
pub fn path(&self) -> Option<&Path> {
self.path.as_deref()
}
pub fn cache_size_bytes(&self) -> usize {
self.cache_size_mb * 1024 * 1024
}
}
impl Default for DatabaseConfig {
fn default() -> Self {
Self::memory()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = DatabaseConfig::default();
assert!(config.is_memory());
assert_eq!(config.cache_size_mb, 64);
assert_eq!(config.default_timeout, Duration::from_secs(30));
}
#[test]
fn test_memory_config() {
let config = DatabaseConfig::memory();
assert!(config.is_memory());
assert!(config.path.is_none());
}
#[test]
fn test_file_config() {
let config = DatabaseConfig::file("/tmp/test.db");
assert!(!config.is_memory());
assert_eq!(config.path(), Some(Path::new("/tmp/test.db")));
}
#[test]
fn test_chain_config() {
let config = DatabaseConfig::memory()
.with_cache_size(128)
.with_timeout(Duration::from_secs(60))
.with_wal(false)
.with_sync_mode(SyncMode::Full);
assert_eq!(config.cache_size_mb, 128);
assert_eq!(config.default_timeout, Duration::from_secs(60));
assert!(!config.enable_wal);
assert_eq!(config.sync_mode, SyncMode::Full);
}
#[test]
fn test_cache_size_bytes() {
let config = DatabaseConfig::memory().with_cache_size(64);
assert_eq!(config.cache_size_bytes(), 64 * 1024 * 1024);
}
#[test]
fn test_sync_mode_default() {
let mode = SyncMode::default();
assert_eq!(mode, SyncMode::Normal);
}
}