dk_engine/graph/
vector.rs1use async_trait::async_trait;
8use uuid::Uuid;
9
10#[derive(Debug, Clone)]
12pub struct VectorSearchResult {
13 pub symbol_id: Uuid,
14 pub score: f32,
15}
16
17#[async_trait]
19pub trait VectorSearch: Send + Sync + 'static {
20 async fn index_embedding(
21 &self,
22 symbol_id: Uuid,
23 repo_id: Uuid,
24 embedding: Vec<f32>,
25 ) -> anyhow::Result<()>;
26
27 async fn search_similar(
28 &self,
29 repo_id: Uuid,
30 query_embedding: Vec<f32>,
31 limit: usize,
32 ) -> anyhow::Result<Vec<VectorSearchResult>>;
33
34 async fn delete_embedding(&self, symbol_id: Uuid) -> anyhow::Result<()>;
35}
36
37pub struct NoOpVectorSearch;
39
40#[async_trait]
41impl VectorSearch for NoOpVectorSearch {
42 async fn index_embedding(
43 &self,
44 _symbol_id: Uuid,
45 _repo_id: Uuid,
46 _embedding: Vec<f32>,
47 ) -> anyhow::Result<()> {
48 Ok(())
49 }
50
51 async fn search_similar(
52 &self,
53 _repo_id: Uuid,
54 _query_embedding: Vec<f32>,
55 _limit: usize,
56 ) -> anyhow::Result<Vec<VectorSearchResult>> {
57 Ok(vec![])
58 }
59
60 async fn delete_embedding(&self, _symbol_id: Uuid) -> anyhow::Result<()> {
61 Ok(())
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[tokio::test]
70 async fn noop_search_returns_empty() {
71 let search = NoOpVectorSearch;
72 let results = search
73 .search_similar(Uuid::new_v4(), vec![0.1, 0.2, 0.3], 10)
74 .await
75 .unwrap();
76 assert!(results.is_empty());
77 }
78
79 #[tokio::test]
80 async fn noop_index_succeeds() {
81 let search = NoOpVectorSearch;
82 search
83 .index_embedding(Uuid::new_v4(), Uuid::new_v4(), vec![0.1, 0.2])
84 .await
85 .unwrap();
86 }
87
88 #[tokio::test]
89 async fn noop_delete_succeeds() {
90 let search = NoOpVectorSearch;
91 search.delete_embedding(Uuid::new_v4()).await.unwrap();
92 }
93}