1#![warn(missing_docs)]
2
3pub mod yni;
4
5use crate::yni::{IndexEngine, YniEngine};
6use std::sync::Arc;
7use tokio::sync::Mutex;
8use uuid::Uuid;
9use yyds_types::{DsResult, DsValue};
10use yykv_wal::WalManager;
11
12pub struct SearchIndexManager {
14 engine: Arc<Mutex<dyn IndexEngine>>,
18}
19
20impl SearchIndexManager {
21 pub fn new_in_memory() -> DsResult<Self> {
22 let engine = YniEngine::new_in_memory();
23
24 Ok(Self {
25 engine: Arc::new(Mutex::new(engine)),
26 })
27 }
28
29 pub async fn index_document(&self, id: Uuid, tenant_id: Uuid, body: String) -> DsResult<()> {
31 let mut engine = self.engine.lock().await;
32 engine.index_text(id, tenant_id, &body).await
33 }
34
35 pub async fn search(
37 &self,
38 query_str: &str,
39 tenant_id: Uuid,
40 limit: usize,
41 ) -> DsResult<Vec<(Uuid, f32)>> {
42 let engine = self.engine.lock().await;
43 engine.search_text(query_str, tenant_id, limit).await
44 }
45
46 pub async fn run_indexer(self: Arc<Self>, wal_manager: Arc<WalManager>) {
48 let mut receiver = wal_manager.subscribe();
49 while let Ok(event) = receiver.recv().await {
50 if (event.table().starts_with("search:") || event.table() == "sys:docs") {
52 if let Some(DsValue::Text(content)) = event.value() {
53 let _ = self
54 .index_document(event.id(), event.tenant_id(), content.clone())
55 .await;
56 }
57 }
58 }
59 }
60}