1use crate::core::config::try_team_salt;
5use crate::core::event::{Event, SessionRecord};
6use crate::search::extract_doc;
7use crate::search::writer::{PendingWriter, index_dir};
8use anyhow::Result;
9use std::collections::BTreeMap;
10use std::path::Path;
11
12#[derive(Debug, Clone, Copy, serde::Serialize)]
13pub struct ReindexStats {
14 pub events_seen: u64,
15 pub docs_indexed: u64,
16}
17
18pub fn reindex_workspace(
19 root: &Path,
20 workspace: &Path,
21 sessions: &[SessionRecord],
22 events: Vec<(SessionRecord, Event)>,
23 cfg: &crate::core::config::Config,
24) -> Result<ReindexStats> {
25 drop_index(root)?;
26 let salt = try_team_salt(&cfg.sync).unwrap_or([0; 32]);
27 let session_map = sessions
28 .iter()
29 .map(|s| (s.id.clone(), s.clone()))
30 .collect::<BTreeMap<_, _>>();
31 let mut writer = PendingWriter::open(root)?;
32 let mut stats = ReindexStats {
33 events_seen: events.len() as u64,
34 docs_indexed: 0,
35 };
36 for (_, event) in events {
37 let Some(session) = session_map.get(&event.session_id) else {
38 continue;
39 };
40 if let Some(doc) = extract_doc(&event, session, workspace, &salt) {
41 writer.add(&doc)?;
42 stats.docs_indexed += 1;
43 }
44 }
45 writer.commit()?;
46 Ok(stats)
47}
48
49fn drop_index(root: &Path) -> Result<()> {
50 let dir = index_dir(root);
51 if dir.exists() {
52 std::fs::remove_dir_all(&dir)?;
53 }
54 Ok(())
55}