use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use gradatum_cache::{EffectiveNoteCache, EffectiveNoteCacheConfig};
use gradatum_core::config::VaultConfig;
use gradatum_core::error::GradatumError;
use gradatum_core::scope::VaultId;
use gradatum_index::SqliteIndex;
use gradatum_storage::{FileStorage, Storage as _};
use crate::error::VaultError;
pub struct Vault {
pub(crate) root: PathBuf,
pub(crate) tenant_id: VaultId,
pub(crate) config: VaultConfig,
pub(crate) storage: FileStorage,
pub(crate) index: Arc<SqliteIndex>,
pub(crate) cache: Arc<EffectiveNoteCache>,
pub(crate) cache_hits: Arc<AtomicU64>,
}
impl Vault {
pub async fn create(root: &Path, tenant_id: VaultId) -> Result<Self, VaultError> {
let storage = FileStorage::new(root)
.map_err(|e| GradatumError::Storage(format!("FileStorage init: {e}")))?;
storage
.create_dir(&format!("{}/", tenant_id.as_str()))
.await
.map_err(|e| GradatumError::Storage(format!("create vault dir: {e}")))?;
storage
.create_dir(".gradatum/")
.await
.map_err(|e| GradatumError::Storage(format!("create .gradatum dir: {e}")))?;
storage
.create_dir(&format!(".gradatum/overrides/{}/", tenant_id.as_str()))
.await
.map_err(|e| GradatumError::Storage(format!("create overrides dir: {e}")))?;
let index_path = root.join(".gradatum").join("index.db");
let index = SqliteIndex::open(&index_path).await?;
let config = VaultConfig::load_from_root(root).map_err(GradatumError::from)?;
let cache = EffectiveNoteCache::new(EffectiveNoteCacheConfig::default());
Ok(Self {
root: root.to_path_buf(),
tenant_id,
config,
storage,
index: Arc::new(index),
cache: Arc::new(cache),
cache_hits: Arc::new(AtomicU64::new(0)),
})
}
pub async fn open(root: &Path) -> Result<Self, VaultError> {
let config = VaultConfig::load_from_root(root).map_err(GradatumError::from)?;
let tenant_id = VaultId::new(
config
.vault
.default_tenant_id
.clone()
.unwrap_or_else(|| "main".into()),
);
let storage = FileStorage::new(root)
.map_err(|e| GradatumError::Storage(format!("FileStorage init: {e}")))?;
let index_path = root.join(".gradatum").join("index.db");
let index = SqliteIndex::open(&index_path).await?;
let cache = EffectiveNoteCache::new(EffectiveNoteCacheConfig::default());
Ok(Self {
root: root.to_path_buf(),
tenant_id,
config,
storage,
index: Arc::new(index),
cache: Arc::new(cache),
cache_hits: Arc::new(AtomicU64::new(0)),
})
}
pub fn root(&self) -> &Path {
&self.root
}
pub fn tenant_id(&self) -> &VaultId {
&self.tenant_id
}
pub fn config(&self) -> &VaultConfig {
&self.config
}
pub fn index(&self) -> &std::sync::Arc<gradatum_index::SqliteIndex> {
&self.index
}
pub fn cache_hits(&self) -> u64 {
self.cache_hits.load(Ordering::Relaxed)
}
}