Skip to main content

relay_knowledge/storage/sqlite/
code.rs

1use rusqlite::Connection;
2
3#[path = "code_query.rs"]
4mod code_query;
5
6#[path = "code_query_prepare.rs"]
7mod code_query_prepare;
8
9#[path = "code_query_hits.rs"]
10mod code_query_hits;
11
12#[path = "code_feature_flags.rs"]
13mod code_feature_flags;
14
15#[path = "code_query_scope.rs"]
16mod code_query_scope;
17
18#[path = "code_impact.rs"]
19mod code_impact;
20
21#[path = "code_report.rs"]
22pub(super) mod code_report;
23
24#[path = "code_schema.rs"]
25mod code_schema;
26
27#[path = "code_status.rs"]
28mod code_status;
29
30#[path = "code_batch.rs"]
31mod code_batch;
32
33#[path = "code_cleanup.rs"]
34mod code_cleanup;
35
36#[path = "code_tasks.rs"]
37mod code_tasks;
38
39#[path = "code_search.rs"]
40mod code_search;
41
42#[path = "code_snapshot.rs"]
43mod code_snapshot;
44
45#[path = "code_set.rs"]
46mod code_set;
47
48#[path = "code_set_tasks.rs"]
49mod code_set_tasks;
50
51#[cfg(test)]
52#[path = "code_tests.rs"]
53mod code_tests;
54
55#[cfg(test)]
56#[path = "code_snapshot_candidate_paths_tests.rs"]
57mod code_snapshot_candidate_paths_tests;
58
59#[cfg(test)]
60#[path = "code_incremental_search_tests.rs"]
61mod code_incremental_search_tests;
62
63#[cfg(test)]
64#[path = "code_batch_finalize_tests.rs"]
65mod code_batch_finalize_tests;
66
67#[cfg(test)]
68#[path = "code_batch_finalize_typescript_tests.rs"]
69mod code_batch_finalize_typescript_tests;
70
71#[cfg(test)]
72#[path = "code_cross_language_call_tests.rs"]
73mod code_cross_language_call_tests;
74
75#[cfg(test)]
76#[path = "code_batch_search_tests.rs"]
77mod code_batch_search_tests;
78
79#[cfg(test)]
80#[path = "code_snapshot_progress_tests.rs"]
81mod code_snapshot_progress_tests;
82
83#[cfg(test)]
84#[path = "code_query_accuracy_tests.rs"]
85mod code_query_accuracy_tests;
86
87#[cfg(test)]
88#[path = "code_query_import_target_tests.rs"]
89mod code_query_import_target_tests;
90
91#[cfg(test)]
92#[path = "code_query_import_ranking_tests.rs"]
93mod code_query_import_ranking_tests;
94
95#[cfg(test)]
96#[path = "code_query_sbom_tests.rs"]
97mod code_query_sbom_tests;
98
99#[cfg(test)]
100#[path = "code_query_line_context_tests.rs"]
101mod code_query_line_context_tests;
102
103#[cfg(test)]
104#[path = "code_metadata_tests.rs"]
105mod code_metadata_tests;
106
107#[cfg(test)]
108#[path = "code_tasks_tests.rs"]
109mod code_tasks_tests;
110
111#[cfg(test)]
112#[path = "code_set_tasks_tests.rs"]
113mod code_set_tasks_tests;
114
115#[cfg(test)]
116#[path = "code_set_tests.rs"]
117mod code_set_tests;
118
119use crate::{
120    domain::{
121        CodeFeatureFlagGraph, CodeFeatureFlagRequest, CodeFileFingerprint, CodeImpactRequest,
122        CodeIndexBatch, CodeIndexCheckpoint, CodeIndexSession, CodeIndexSnapshot, CodeIndexSummary,
123        CodeRepositoryRegistration, CodeRepositoryReport, CodeRepositoryStatus,
124        CodeRepositoryTotals, CodeRetrievalHit, CodeRetrievalRequest,
125    },
126    storage::{CodeImpactChanges, CodeRepositoryStore, StorageError, StorageFuture},
127};
128
129use super::SqliteGraphStore;
130pub(super) use code_search::SearchDocumentInserter;
131
132const MAX_SYMBOL_SIGNATURE_LOOKUP_IDS_PER_STATEMENT: usize = 500;
133
134pub(super) fn initialize_code_schema(connection: &Connection) -> Result<(), StorageError> {
135    code_schema::initialize_code_schema(connection)
136}
137
138impl CodeRepositoryStore for SqliteGraphStore {
139    fn upsert_code_repository(
140        &self,
141        registration: CodeRepositoryRegistration,
142    ) -> StorageFuture<'_, CodeRepositoryStatus> {
143        self.run(move |connection| code_status::upsert_repository(connection, registration))
144    }
145
146    fn code_repository_status(
147        &self,
148        repository: String,
149    ) -> StorageFuture<'_, Option<CodeRepositoryStatus>> {
150        self.run_read(move |connection| code_status::repository_status(connection, &repository))
151    }
152
153    fn code_repository_scope_status(
154        &self,
155        repository: String,
156        resolved_commit_sha: String,
157        path_filters: Vec<String>,
158        language_filters: Vec<String>,
159    ) -> StorageFuture<'_, Option<CodeRepositoryStatus>> {
160        self.run_read(move |connection| {
161            code_status::repository_scope_status(
162                connection,
163                &repository,
164                &resolved_commit_sha,
165                &path_filters,
166                &language_filters,
167            )
168        })
169    }
170
171    fn latest_code_repository_scope_status(
172        &self,
173        repository: String,
174        path_filters: Vec<String>,
175        language_filters: Vec<String>,
176    ) -> StorageFuture<'_, Option<CodeRepositoryStatus>> {
177        self.run_read(move |connection| {
178            code_status::latest_repository_scope_status(
179                connection,
180                &repository,
181                &path_filters,
182                &language_filters,
183            )
184        })
185    }
186
187    fn queue_code_index_task(
188        &self,
189        task: crate::storage::CodeIndexTaskSeed,
190    ) -> StorageFuture<'_, crate::domain::CodeIndexTaskRecord> {
191        self.run(move |connection| code_tasks::queue_task(connection, task))
192    }
193
194    fn claim_code_index_task(
195        &self,
196        request: crate::storage::CodeIndexTaskClaimRequest,
197    ) -> StorageFuture<'_, Option<crate::domain::CodeIndexTaskRecord>> {
198        self.run(move |connection| code_tasks::claim_task(connection, request))
199    }
200
201    fn recover_code_index_task_leases(
202        &self,
203        now_ms: u64,
204        max_attempts: u32,
205    ) -> StorageFuture<'_, ()> {
206        self.run(move |connection| {
207            code_tasks::recover_expired_task_leases(connection, now_ms, max_attempts)
208        })
209    }
210
211    fn renew_code_index_task_lease(
212        &self,
213        request: crate::storage::CodeIndexTaskLeaseRenewal,
214    ) -> StorageFuture<'_, crate::domain::CodeIndexTaskRecord> {
215        self.run(move |connection| code_tasks::renew_task_lease(connection, request))
216    }
217
218    fn complete_code_index_task(
219        &self,
220        request: crate::storage::CodeIndexTaskCompletion,
221    ) -> StorageFuture<'_, crate::domain::CodeIndexTaskRecord> {
222        self.run(move |connection| code_tasks::complete_task(connection, request))
223    }
224
225    fn fail_code_index_task(
226        &self,
227        request: crate::storage::CodeIndexTaskFailure,
228    ) -> StorageFuture<'_, crate::domain::CodeIndexTaskRecord> {
229        self.run(move |connection| code_tasks::fail_task(connection, request))
230    }
231
232    fn code_index_task(
233        &self,
234        task_id: String,
235    ) -> StorageFuture<'_, Option<crate::domain::CodeIndexTaskRecord>> {
236        self.run_read(move |connection| code_tasks::task_by_id(connection, &task_id))
237    }
238
239    fn active_code_index_task(
240        &self,
241        repository_id: String,
242    ) -> StorageFuture<'_, Option<crate::domain::CodeIndexTaskRecord>> {
243        self.run_read(move |connection| code_tasks::active_task(connection, &repository_id))
244    }
245
246    fn code_index_checkpoint(
247        &self,
248        source_scope: String,
249    ) -> StorageFuture<'_, Option<crate::domain::CodeIndexCheckpoint>> {
250        self.run_read(move |connection| code_tasks::checkpoint(connection, &source_scope))
251    }
252
253    fn code_scope_retention(
254        &self,
255        repository_id: String,
256    ) -> StorageFuture<'_, crate::domain::CodeScopeRetentionSummary> {
257        self.run_read(move |connection| code_tasks::retention_status(connection, &repository_id))
258    }
259
260    fn prune_code_repository_scopes(
261        &self,
262        request: crate::storage::CodeScopeRetentionRequest,
263    ) -> StorageFuture<'_, crate::domain::CodeScopeRetentionSummary> {
264        self.run(move |connection| code_tasks::prune_scopes(connection, request))
265    }
266
267    fn code_file_fingerprints(
268        &self,
269        repository_id: String,
270    ) -> StorageFuture<'_, Vec<CodeFileFingerprint>> {
271        self.run_read(move |connection| {
272            code_snapshot::file_fingerprints(connection, &repository_id)
273        })
274    }
275
276    fn code_file_fingerprints_for_scope(
277        &self,
278        source_scope: String,
279    ) -> StorageFuture<'_, Vec<CodeFileFingerprint>> {
280        self.run_read(move |connection| {
281            code_snapshot::file_fingerprints_for_scope(connection, &source_scope)
282        })
283    }
284
285    fn code_file_candidate_paths_for_scope(
286        &self,
287        source_scope: String,
288        path_filters: Vec<String>,
289        language_filters: Vec<String>,
290        limit: usize,
291    ) -> StorageFuture<'_, Vec<String>> {
292        self.run_read(move |connection| {
293            code_snapshot::file_candidate_paths_for_scope(
294                connection,
295                &source_scope,
296                &path_filters,
297                &language_filters,
298                limit,
299            )
300        })
301    }
302
303    fn code_file_candidate_paths_for_query_scope(
304        &self,
305        source_scope: String,
306        query: String,
307        path_filters: Vec<String>,
308        language_filters: Vec<String>,
309        limit: usize,
310    ) -> StorageFuture<'_, Vec<String>> {
311        self.run_read(move |connection| {
312            code_snapshot::file_candidate_paths_for_query_scope(
313                connection,
314                &source_scope,
315                &query,
316                &path_filters,
317                &language_filters,
318                limit,
319            )
320        })
321    }
322
323    fn apply_code_index_snapshot(
324        &self,
325        snapshot: CodeIndexSnapshot,
326    ) -> StorageFuture<'_, CodeIndexSummary> {
327        self.run(move |connection| code_snapshot::apply_snapshot(connection, snapshot))
328    }
329
330    fn begin_code_index_session(
331        &self,
332        session: CodeIndexSession,
333    ) -> StorageFuture<'_, CodeIndexCheckpoint> {
334        self.run(move |connection| code_batch::begin_session(connection, session))
335    }
336
337    fn apply_code_index_batch(
338        &self,
339        batch: CodeIndexBatch,
340    ) -> StorageFuture<'_, CodeIndexCheckpoint> {
341        self.run(move |connection| code_batch::apply_batch(connection, batch))
342    }
343
344    fn finalize_code_index_session(
345        &self,
346        session: CodeIndexSession,
347    ) -> StorageFuture<'_, CodeIndexSummary> {
348        self.run(move |connection| code_batch::finalize_session(connection, session))
349    }
350
351    fn search_code(
352        &self,
353        request: CodeRetrievalRequest,
354    ) -> StorageFuture<'_, Vec<CodeRetrievalHit>> {
355        self.run_read(move |connection| code_query::search_code(connection, request))
356    }
357
358    fn search_code_feature_flags(
359        &self,
360        request: CodeFeatureFlagRequest,
361    ) -> StorageFuture<'_, Vec<CodeFeatureFlagGraph>> {
362        self.run_read(move |connection| code_feature_flags::search(connection, request))
363    }
364
365    fn search_code_feature_flags_scope(
366        &self,
367        source_scope: String,
368        request: CodeFeatureFlagRequest,
369    ) -> StorageFuture<'_, Vec<CodeFeatureFlagGraph>> {
370        self.run_read(move |connection| {
371            code_feature_flags::search_scope(connection, &source_scope, request)
372        })
373    }
374
375    fn search_code_scope(
376        &self,
377        source_scope: String,
378        request: CodeRetrievalRequest,
379    ) -> StorageFuture<'_, Vec<CodeRetrievalHit>> {
380        self.run_read(move |connection| {
381            code_query::search_code_scope(connection, &source_scope, request)
382        })
383    }
384
385    fn analyze_code_impact(
386        &self,
387        request: CodeImpactRequest,
388        changes: CodeImpactChanges,
389    ) -> StorageFuture<'_, Vec<CodeRetrievalHit>> {
390        self.run_read(move |connection| code_impact::analyze_impact(connection, request, changes))
391    }
392
393    fn code_repository_totals(&self) -> StorageFuture<'_, CodeRepositoryTotals> {
394        self.run_read(code_report::repository_totals)
395    }
396
397    fn code_repository_report(
398        &self,
399        repository: String,
400    ) -> StorageFuture<'_, CodeRepositoryReport> {
401        self.run_read(move |connection| code_report::repository_report(connection, &repository))
402    }
403
404    fn create_code_repository_set(
405        &self,
406        seed: crate::storage::CodeRepositorySetSeed,
407    ) -> StorageFuture<'_, crate::domain::CodeRepositorySet> {
408        self.run(move |connection| code_set::create_set(connection, seed))
409    }
410
411    fn add_code_repository_set_member(
412        &self,
413        seed: crate::storage::CodeRepositorySetMemberSeed,
414    ) -> StorageFuture<'_, crate::domain::CodeRepositorySetMember> {
415        self.run(move |connection| code_set::add_member(connection, seed))
416    }
417
418    fn remove_code_repository_set_member(
419        &self,
420        set_alias: String,
421        repository_alias: String,
422    ) -> StorageFuture<'_, crate::domain::CodeRepositorySetMember> {
423        self.run(move |connection| {
424            code_set::remove_member(connection, &set_alias, &repository_alias)
425        })
426    }
427
428    fn code_repository_set(
429        &self,
430        set_alias: String,
431    ) -> StorageFuture<'_, Option<crate::domain::CodeRepositorySet>> {
432        self.run_read(move |connection| code_set::set_by_alias(connection, &set_alias))
433    }
434
435    fn code_repository_set_status(
436        &self,
437        set_alias: String,
438    ) -> StorageFuture<'_, Option<crate::domain::CodeRepositorySetStatus>> {
439        self.run_read(move |connection| code_set::set_status(connection, &set_alias))
440    }
441
442    fn refresh_code_repository_set_overlay(
443        &self,
444        set_alias: String,
445        now_ms: u64,
446    ) -> StorageFuture<'_, crate::domain::CodeRepositorySetRefreshSummary> {
447        self.run(move |connection| code_set::refresh_overlay(connection, &set_alias, now_ms))
448    }
449
450    fn code_repository_set_cross_edges(
451        &self,
452        set_id: String,
453    ) -> StorageFuture<'_, Vec<crate::domain::CodeRepositoryCrossEdge>> {
454        self.run_read(move |connection| code_set::cross_edges_for_set(connection, &set_id))
455    }
456
457    fn queue_code_repository_set_refresh_task(
458        &self,
459        task: crate::storage::CodeRepositorySetRefreshTaskSeed,
460    ) -> StorageFuture<'_, crate::domain::CodeRepositorySetRefreshTaskRecord> {
461        self.run(move |connection| code_set_tasks::queue_refresh_task(connection, task))
462    }
463
464    fn claim_code_repository_set_refresh_task(
465        &self,
466        request: crate::storage::CodeRepositorySetRefreshTaskClaimRequest,
467    ) -> StorageFuture<'_, Option<crate::domain::CodeRepositorySetRefreshTaskRecord>> {
468        self.run(move |connection| code_set_tasks::claim_refresh_task(connection, request))
469    }
470
471    fn complete_code_repository_set_refresh_task(
472        &self,
473        request: crate::storage::CodeRepositorySetRefreshTaskCompletion,
474    ) -> StorageFuture<'_, crate::domain::CodeRepositorySetRefreshTaskRecord> {
475        self.run(move |connection| code_set_tasks::complete_refresh_task(connection, request))
476    }
477
478    fn fail_code_repository_set_refresh_task(
479        &self,
480        request: crate::storage::CodeRepositorySetRefreshTaskFailure,
481    ) -> StorageFuture<'_, crate::domain::CodeRepositorySetRefreshTaskRecord> {
482        self.run(move |connection| code_set_tasks::fail_refresh_task(connection, request))
483    }
484}