Keep prepared search readers warm and verify abrupt indexing recovery

This commit is contained in:
karl committed 2026-10-13 01:36:34 +02:00
1 parent 423a1ea57d
commit 6b78c8bb7f
17 files changed
+1011 -41

No files matched your search

@@ -3,9 +3,25 @@
"release": "autobuild-2026-10-12-13-12",
"version": "9.0.2-27-g7e93014c5b",
"platforms": {
"windows-x86_64": {"archive": "ffmpeg-n9.0.2-27-g7e93014c5b-win64-lgpl-9.0.zip", "bytes": 171476229, "sha256": "104a019fe34c0747b208bde4842a0bac8b70a307cc2bb33aa4648fc15ddb2e39"},
"windows-aarch64": {"archive": "ffmpeg-n9.0.2-27-g7e93014c5b-winarm64-lgpl-9.0.zip", "bytes": 118006941, "sha256": "68d3bac585b80b6f17e459eb4a203ed1f01b7635d4c611f1685de1ae65ca0987"},
"linux-x86_64": {"archive": "ffmpeg-n9.0.2-27-g7e93014c5b-linux64-lgpl-9.0.tar.xz", "bytes": 137901812, "sha256": "12445b38a4700ba1ae7c9c7e57062f602c927dc4187555bfadc9f3e2f75f05b0"},
"linux-aarch64": {"archive": "ffmpeg-n9.0.2-27-g7e93014c5b-linuxarm64-lgpl-9.0.tar.xz", "bytes": 117008524, "sha256": "c9160ae8440c17c016fb2f6b3fcce4bb9d633a15845e908b2303948a7724f227"}
"windows-x86_64": {
"archive": "ffmpeg-n9.0.2-27-g7e93014c5b-win64-lgpl-9.0.zip",
"bytes": 171476229,
"sha256": "104a019fe34c0747b208bde4842a0bac8b70a307cc2bb33aa4648fc15ddb2e39"
},
"windows-aarch64": {
"archive": "ffmpeg-n9.0.2-27-g7e93014c5b-winarm64-lgpl-9.0.zip",
"bytes": 118006941,
"sha256": "68d3bac585b80b6f17e459eb4a203ed1f01b7635d4c611f1685de1ae65ca0987"
},
"linux-x86_64": {
"archive": "ffmpeg-n9.0.2-27-g7e93014c5b-linux64-lgpl-9.0.tar.xz",
"bytes": 137901812,
"sha256": "12445b38a4700ba1ae7c9c7e57062f602c927dc4187555bfadc9f3e2f75f05b0"
},
"linux-aarch64": {
"archive": "ffmpeg-n9.0.2-27-g7e93014c5b-linuxarm64-lgpl-9.0.tar.xz",
"bytes": 117008524,
"sha256": "c9160ae8440c17c016fb2f6b3fcce4bb9d633a15845e908b2303948a7724f227"
}
}
}
@@ -25,6 +25,7 @@ pub struct SemanticState {
downloaded_bytes: AtomicU64,
error: Mutex<Option<String>>,
service: Mutex<Option<HybridSearch>>,
prepared_graphs: searchi_service::PreparedGraphs,
media_tools: Option<searchi_media::FfmpegTools>,
media_setup_error: Option<String>,
}
@@ -51,6 +52,7 @@ impl SemanticState {
downloaded_bytes: AtomicU64::new(0),
error: Mutex::new(None),
service: Mutex::new(None),
prepared_graphs: searchi_service::PreparedGraphs::default(),
media_tools,
media_setup_error,
}
@@ -76,6 +78,9 @@ impl SemanticState {
let mut service =
HybridSearch::open(database, &self.model_directory, &self.worker, threads)
.map_err(|error| error.to_string())?;
service
.share_prepared_graphs(&self.prepared_graphs)
.map_err(|error| error.to_string())?;
service.warmup().map_err(|error| error.to_string())?;
*self
.service
@@ -242,36 +247,15 @@ pub async fn index_embeddings(state: State<'_, AppState>) -> Result<EmbeddingRep
threads,
)
.and_then(|mut service| {
service.share_prepared_graphs(&semantic.prepared_graphs)?;
let tools = semantic.media_tools.as_ref().ok_or_else(|| {
anyhow::anyhow!("The media decoder is missing from this installation. Repair or reinstall searchi.")
})?;
service.index_embeddings_with_media(tools, &searchi_media::MediaLimits::default())
})
.map_err(|error| error.to_string());
// Prepare the newly activated graph before advertising semantic readiness.
// Keyword search stays available while the cached query session catches up.
if result.is_ok() {
semantic.warmed.store(false, Ordering::Release);
semantic.warming.store(true, Ordering::Release);
let _warming_guard = WorkGuard(&semantic.warming);
let preparation = (|| {
let mut cached = semantic
.service
.lock()
.map_err(|_| "Semantic session is unavailable.".to_string())?;
let service = cached
.as_mut()
.ok_or_else(|| "Semantic query session has not been prepared.".to_string())?;
service.warmup().map_err(|error| error.to_string())
})();
semantic.warmed.store(preparation.is_ok(), Ordering::Release);
if let Err(error) = preparation {
semantic.record_error(Some(format!(
"The index was saved, but search preparation failed: {error}"
)));
return result;
}
}
// The publisher shares its prepared immutable ANN before activation.
// Keep the query model and its cached vectors warm throughout indexing.
semantic.record_error(result.as_ref().err().cloned());
result
})