use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum DataClass {
PersistentCatalog,
RebuildableIndex,
EphemeralCache,
LocalDependency,
OperationalLog,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum StorageCategory {
PersistentCatalog,
KeywordIndex,
VectorIndex,
SnippetCache,
SearchCache,
TemporaryExtraction,
ModelFiles,
Logs,
}
impl StorageCategory {
pub const ALL: [StorageCategory; 8] = [
StorageCategory::PersistentCatalog,
StorageCategory::KeywordIndex,
StorageCategory::VectorIndex,
StorageCategory::SnippetCache,
StorageCategory::SearchCache,
StorageCategory::TemporaryExtraction,
StorageCategory::ModelFiles,
StorageCategory::Logs,
];
pub fn as_str(&self) -> &'static str {
match self {
StorageCategory::PersistentCatalog => "persistent_catalog",
StorageCategory::KeywordIndex => "keyword_index",
StorageCategory::VectorIndex => "vector_index",
StorageCategory::SnippetCache => "snippet_cache",
StorageCategory::SearchCache => "search_cache",
StorageCategory::TemporaryExtraction => "temporary_extraction",
StorageCategory::ModelFiles => "model_files",
StorageCategory::Logs => "logs",
}
}
pub fn data_class(&self) -> DataClass {
match self {
StorageCategory::PersistentCatalog => DataClass::PersistentCatalog,
StorageCategory::KeywordIndex | StorageCategory::VectorIndex => {
DataClass::RebuildableIndex
}
StorageCategory::SnippetCache
| StorageCategory::SearchCache
| StorageCategory::TemporaryExtraction => DataClass::EphemeralCache,
StorageCategory::ModelFiles => DataClass::LocalDependency,
StorageCategory::Logs => DataClass::OperationalLog,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CleanupAction {
ClearExpiredSearchCache,
ClearSnippetCache,
ClearTemporaryExtraction,
RemoveReplacedStaleIndexes,
DeleteKeywordIndex,
DeleteVectorIndex,
RemoveTemporarySourceIndexes,
ResetCatalog,
}
impl CleanupAction {
pub fn affected_classes(&self) -> &'static [DataClass] {
match self {
CleanupAction::ClearExpiredSearchCache
| CleanupAction::ClearSnippetCache
| CleanupAction::ClearTemporaryExtraction => &[DataClass::EphemeralCache],
CleanupAction::RemoveReplacedStaleIndexes
| CleanupAction::DeleteKeywordIndex
| CleanupAction::DeleteVectorIndex
| CleanupAction::RemoveTemporarySourceIndexes => &[DataClass::RebuildableIndex],
CleanupAction::ResetCatalog => &[
DataClass::PersistentCatalog,
DataClass::RebuildableIndex,
DataClass::EphemeralCache,
DataClass::OperationalLog,
],
}
}
pub fn requires_rebuild(&self) -> bool {
!matches!(
self,
CleanupAction::ClearExpiredSearchCache
| CleanupAction::ClearSnippetCache
| CleanupAction::ClearTemporaryExtraction
)
}
pub fn requires_confirmation(&self) -> bool {
self.requires_rebuild()
}
pub fn touches_persistent_catalog(&self) -> bool {
self.affected_classes()
.contains(&DataClass::PersistentCatalog)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CleanupPlan {
pub action: CleanupAction,
pub affected_classes: Vec<DataClass>,
pub estimated_recovered_bytes: u64,
pub requires_rebuild: bool,
pub requires_confirmation: bool,
}
impl CleanupPlan {
pub fn for_action(action: CleanupAction, estimated_recovered_bytes: u64) -> Self {
Self {
action,
affected_classes: action.affected_classes().to_vec(),
estimated_recovered_bytes,
requires_rebuild: action.requires_rebuild(),
requires_confirmation: action.requires_confirmation(),
}
}
pub fn assert_safe_for_ordinary_cleanup(&self) -> Result<(), crate::error::OrbokError> {
if self
.affected_classes
.contains(&DataClass::PersistentCatalog)
{
return Err(crate::error::OrbokError::CleanupWouldTouchPersistentData);
}
Ok(())
}
}