use std::path::Path;
use lean_semantic_search_retrieval::RETRIEVAL_POLICY_VERSION;
use crate::StoreError;
use crate::lifecycle;
use crate::read::Store;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum CacheMiss {
Missing,
TokenMismatch,
SchemaDrift,
PolicyDrift,
Corrupt,
}
pub enum CorpusLookup {
Fresh(Store),
Stale(CacheMiss),
}
impl std::fmt::Debug for CorpusLookup {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Fresh(_) => formatter.write_str("Fresh(..)"),
Self::Stale(miss) => write!(formatter, "Stale({miss:?})"),
}
}
}
impl Store {
#[must_use]
pub fn open_fresh(path: impl AsRef<Path>, expected_token: &str) -> CorpusLookup {
let path = path.as_ref();
if !path.exists() {
return CorpusLookup::Stale(CacheMiss::Missing);
}
match Self::open(path) {
Ok(store) => {
if store.corpus_token() != expected_token {
CorpusLookup::Stale(CacheMiss::TokenMismatch)
} else if store.policy_version() != RETRIEVAL_POLICY_VERSION {
CorpusLookup::Stale(CacheMiss::PolicyDrift)
} else {
CorpusLookup::Fresh(store)
}
}
Err(StoreError::SchemaMismatch { .. }) => CorpusLookup::Stale(CacheMiss::SchemaDrift),
Err(_) => CorpusLookup::Stale(CacheMiss::Corrupt),
}
}
}
#[must_use]
pub fn open_latest_fresh(root: &Path, expected_token: &str) -> CorpusLookup {
match lifecycle::latest_index_path(root) {
Some(index) => Store::open_fresh(index, expected_token),
None => CorpusLookup::Stale(CacheMiss::Missing),
}
}