fix(search): prevent memory leaks and duplication in tantivy search index by explicitly deleting prior terms during updates and syncing store deletions

This commit is contained in:
Riz Ashraf committed 2026-09-21 19:16:55 +01:00
1 parent 7dc0c329ad
commit af2c4ab046
4 files changed
+42 -5

No files matched your search

+26 -2
View File
@@ -57,6 +57,8 @@ impl MemoryIndex {
pub fn index_entity(&self, e: &Entity) -> tokio::task::JoinHandle<tantivy::Result<()>> {
let writer = Arc::clone(&self.writer);
let id_field = self.id_field;
let id_val = e.name.clone();
let doc = doc!(
self.id_field => e.name.as_str(),
@@ -68,6 +70,7 @@ impl MemoryIndex {
tokio::task::spawn_blocking(move || {
let writer = writer.lock().unwrap_or_else(|e| e.into_inner());
writer.delete_term(tantivy::Term::from_field_text(id_field, &id_val));
writer.add_document(doc)?;
Ok(())
})
@@ -75,22 +78,37 @@ impl MemoryIndex {
pub fn index_task(&self, t: &Task) -> tokio::task::JoinHandle<tantivy::Result<()>> {
let writer = Arc::clone(&self.writer);
let id_field = self.id_field;
let id_val = t.id.clone();
let doc = doc!(
self.id_field => t.id.as_str(),
self.title_field => t.title.as_str(),
self.body_field => t.description.as_str(),
self.body_field => format!("{}\n{}", t.description, t.acceptance_criteria.iter().map(|c| c.description.as_str()).collect::<Vec<_>>().join("\n")),
self.type_field => "task",
self.namespace_field => "global"
);
tokio::task::spawn_blocking(move || {
let writer = writer.lock().unwrap_or_else(|e| e.into_inner());
writer.delete_term(tantivy::Term::from_field_text(id_field, &id_val));
writer.add_document(doc)?;
Ok(())
})
}
pub fn delete_document(&self, id: &str) -> tokio::task::JoinHandle<tantivy::Result<()>> {
let writer = Arc::clone(&self.writer);
let id_field = self.id_field;
let id_val = id.to_string();
tokio::task::spawn_blocking(move || {
let writer = writer.lock().unwrap_or_else(|e| e.into_inner());
writer.delete_term(tantivy::Term::from_field_text(id_field, &id_val));
Ok(())
})
}
pub async fn commit(&self) -> tantivy::Result<()> {
let writer = Arc::clone(&self.writer);
tokio::task::spawn_blocking(move || {
@@ -162,17 +180,20 @@ impl MemoryIndex {
pub fn index_snippet(&self, s: &Snippet) -> tokio::task::JoinHandle<tantivy::Result<()>> {
let writer = Arc::clone(&self.writer);
let id_field = self.id_field;
let id_val = s.name.clone();
let doc = doc!(
self.id_field => s.name.as_str(),
self.title_field => s.name.as_str(),
self.body_field => format!("{} {}", s.language, s.description),
self.body_field => format!("{} {}\n{}", s.language, s.description, s.code),
self.type_field => "snippet",
self.namespace_field => "global"
);
tokio::task::spawn_blocking(move || {
let writer = writer.lock().unwrap_or_else(|e| e.into_inner());
writer.delete_term(tantivy::Term::from_field_text(id_field, &id_val));
writer.add_document(doc)?;
Ok(())
})
@@ -180,6 +201,8 @@ impl MemoryIndex {
pub fn index_adr(&self, a: &Adr) -> tokio::task::JoinHandle<tantivy::Result<()>> {
let writer = Arc::clone(&self.writer);
let id_field = self.id_field;
let id_val = a.id.clone();
let doc = doc!(
self.id_field => a.id.as_str(),
@@ -191,6 +214,7 @@ impl MemoryIndex {
tokio::task::spawn_blocking(move || {
let writer = writer.lock().unwrap_or_else(|e| e.into_inner());
writer.delete_term(tantivy::Term::from_field_text(id_field, &id_val));
writer.add_document(doc)?;
Ok(())
})