use std::sync::Arc;
use akar_common::types::Value;
use akar_storage::table::TableCatalog;
pub fn sync_indexes_on_commit(
table_catalog: &Arc<TableCatalog>,
fts_indexes: &[(String, String, String)],
written_rows: &[(u64, u64)],
) -> Result<usize, String> {
if fts_indexes.is_empty() || written_rows.is_empty() {
return Ok(0);
}
let Some(base) = table_catalog.db_path() else {
return Ok(0);
};
if base.to_string_lossy() == ":memory:" {
return Ok(0);
}
let written_tables: std::collections::HashSet<u64> = written_rows.iter().map(|(t, _)| *t).collect();
let mut synced = 0usize;
for (name, table_name, column_name) in fts_indexes {
let Some(source_table) = table_catalog.get_node_table_by_name(table_name) else {
continue;
};
let table_id = source_table.table_id;
if !written_tables.contains(&table_id) {
continue;
}
let Some(col_idx) = source_table.columns.iter().position(|c| c.name == *column_name) else {
continue;
};
let index_dir = base.join("fts").join(name);
if !index_dir.join("meta.json").exists() {
tracing::warn!(
"FTS: index '{name}' has no on-disk Tantivy data; skipping commit-time sync \
(rebuild with DROP + CREATE FTS INDEX if the schema changed)"
);
continue;
}
let writes: Vec<(i64, Option<String>)> = {
let mut seen = std::collections::HashSet::with_capacity(written_rows.len());
let mut out = Vec::with_capacity(written_rows.len());
for (tid, row_id) in written_rows {
if *tid != table_id || !seen.insert(*row_id) {
continue;
}
let Ok(row) = usize::try_from(*row_id) else {
continue;
};
let text = match source_table.get_value(row, col_idx) {
Some(Value::String(s)) => Some(s.clone()),
_ => None, };
out.push((*row_id as i64, text));
}
out
};
if writes.is_empty() {
continue;
}
let handle = akar_fts::index::runtime_handle(table_catalog, name, &index_dir)
.map_err(|e| format!("FTS: open index '{name}': {e}"))?;
akar_fts::build::apply_doc_writes(handle.inner(), column_name, &writes)
.map_err(|e| format!("FTS: sync index '{name}': {e}"))?;
handle
.reload()
.map_err(|e| format!("FTS: reload index '{name}': {e}"))?;
synced += writes.len();
}
Ok(synced)
}