Implement Phase B: Crash Recovery
Add startup integrity checks, corruption recovery, CAS size limits, graceful shutdown orchestration, and a task supervisor — turning 5 previously-RED resilience tests GREEN and adding 5 new tests. - CAS: pre-check size limit in put(), add StoreFull error variant - CAS: sled corruption recovery in open() (retry then recreate) - SQLite: open_with_integrity_check() via PRAGMA integrity_check(1) - tantivy: open_with_recovery() deletes and rebuilds corrupt index - CLI: CancellationToken-based ordered shutdown sequence - Core: TaskSupervisor with spawn_supervised/spawn_critical + backoff - Tests: replace 4 todo!() stubs, add 5 new shutdown/supervisor tests
This commit is contained in:
@@ -6,7 +6,7 @@ use tantivy::collector::TopDocs;
|
||||
use tantivy::query::{BooleanQuery, FuzzyTermQuery, Occur, Query, QueryParser};
|
||||
use tantivy::schema::{Field, Schema, Value, STORED, TEXT, INDEXED};
|
||||
use tantivy::{Index, IndexReader, IndexWriter, ReloadPolicy, TantivyDocument, Term};
|
||||
use tracing::{debug, info};
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
const SCHEMA_VERSION: u32 = 1;
|
||||
|
||||
@@ -95,6 +95,28 @@ impl SearchIndex {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn open_with_recovery(index_path: &Path) -> Result<Self, SearchError> {
|
||||
match Self::open(index_path) {
|
||||
Ok(index) => {
|
||||
let docs = index.reader.searcher().num_docs();
|
||||
info!(docs, "Search index opened successfully");
|
||||
Ok(index)
|
||||
}
|
||||
Err(e) => {
|
||||
warn!(
|
||||
error = %e,
|
||||
path = ?index_path,
|
||||
"Search index corrupted, rebuilding from scratch"
|
||||
);
|
||||
if index_path.exists() {
|
||||
std::fs::remove_dir_all(index_path)
|
||||
.map_err(SearchError::Io)?;
|
||||
}
|
||||
Self::open(index_path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn index_file(&self, file: &FileMeta) -> Result<(), SearchError> {
|
||||
let mut doc = TantivyDocument::new();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user