1use crate::domain::{
4 CodeFeatureFlagGraph, CodeFeatureFlagRequest, CodeFileFingerprint, CodeImpactRequest,
5 CodeIndexBatch, CodeIndexCheckpoint, CodeIndexSession, CodeIndexSnapshot, CodeIndexSummary,
6 CodeIndexTaskQueueStatus, CodeIndexTaskRecord, CodeRepositoryCrossEdge,
7 CodeRepositoryRegistration, CodeRepositoryRemovalSummary, CodeRepositoryReport,
8 CodeRepositorySet, CodeRepositorySetMember, CodeRepositorySetRefreshSummary,
9 CodeRepositorySetRefreshTaskRecord, CodeRepositorySetStatus, CodeRepositoryStatus,
10 CodeRepositoryTotals, CodeRetrievalHit, CodeRetrievalRequest, CodeScopeRetentionSummary,
11 CodeSymbolGenerationCounts, CodebaseViewRequest, CodebaseViewSnapshot,
12 SoftwareGlobalProjection, SoftwareGlobalRequest,
13};
14
15use super::{StorageError, StorageFuture};
16
17pub const CODE_INDEX_TASK_LEASE_RECOVERY_UNAVAILABLE: &str =
19 "code index task lease recovery is unavailable";
20
21pub const CODE_INDEX_TASK_LEASE_RENEWAL_UNAVAILABLE: &str =
23 "code index task lease renewal is unavailable";
24
25#[derive(Debug, Clone, Default, PartialEq, Eq)]
27pub struct CodeImpactChanges {
28 pub paths: Vec<String>,
29 pub deleted_symbol_names: Vec<String>,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct CodeIndexTaskSeed {
35 pub repository_id: String,
36 pub alias: String,
37 pub ref_selector: String,
38 pub resolved_commit_sha: String,
39 pub tree_hash: String,
40 pub source_scope: String,
41 pub path_filters: Vec<String>,
42 pub language_filters: Vec<String>,
43 pub mode: crate::domain::CodeIndexMode,
44 pub input_fingerprint: String,
45 pub resource_budget: crate::domain::CodeIndexResourceBudget,
46 pub payload_json: String,
47 pub now_ms: u64,
48}
49
50#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct CodeIndexTaskClaimRequest {
53 pub task_id: Option<String>,
54 pub lease_owner: String,
55 pub lease_duration_ms: u64,
56 pub max_attempts: u32,
57 pub now_ms: u64,
58}
59
60#[derive(Debug, Clone, PartialEq, Eq)]
62pub struct CodeIndexTaskLeaseRenewal {
63 pub task_id: String,
64 pub lease_owner: String,
65 pub attempt_count: u32,
66 pub lease_duration_ms: u64,
67 pub now_ms: u64,
68}
69
70#[derive(Debug, Clone, PartialEq, Eq)]
72pub struct CodeIndexTaskLeaseRecord {
73 pub task_id: String,
74 pub lease_owner: String,
75 pub lease_expires_at_ms: Option<u64>,
76 pub attempt_count: u32,
77}
78
79#[derive(Debug, Clone, PartialEq, Eq)]
81pub struct CodeIndexTaskLeaseRecovery {
82 pub task_ids: Vec<String>,
83 pub now_ms: u64,
84 pub max_attempts: u32,
85 pub error_kind: String,
86 pub error_message: String,
87}
88
89#[derive(Debug, Clone, PartialEq, Eq)]
91pub struct CodeIndexTaskCompletion {
92 pub task_id: String,
93 pub lease_owner: String,
94 pub attempt_count: u32,
95 pub now_ms: u64,
96}
97
98#[derive(Debug, Clone, PartialEq, Eq)]
100pub struct CodeIndexTaskFailure {
101 pub task_id: String,
102 pub lease_owner: String,
103 pub attempt_count: u32,
104 pub error_kind: String,
105 pub error_message: String,
106 pub retry_backoff_ms: u64,
107 pub max_attempts: u32,
108 pub now_ms: u64,
109}
110
111#[derive(Debug, Clone, PartialEq, Eq)]
113pub struct CodeScopeRetentionRequest {
114 pub repository_id: String,
115 pub active_scope: String,
116 pub retain_recent_successful_scopes: usize,
117}
118
119#[derive(Debug, Clone, PartialEq, Eq)]
121pub struct CodeRepositorySetSeed {
122 pub alias: String,
123 pub description: Option<String>,
124 pub default_ref_policy_json: String,
125 pub now_ms: u64,
126}
127
128#[derive(Debug, Clone, PartialEq, Eq)]
130pub struct CodeRepositorySetMemberSeed {
131 pub set_alias: String,
132 pub repository_id: String,
133 pub repository_alias: String,
134 pub ref_selector: String,
135 pub resolved_commit_sha: String,
136 pub source_scope: String,
137 pub path_filters: Vec<String>,
138 pub language_filters: Vec<String>,
139 pub priority: i32,
140}
141
142#[derive(Debug, Clone, PartialEq, Eq)]
144pub struct CodeRepositorySetRefreshTaskSeed {
145 pub set_id: String,
146 pub set_alias: String,
147 pub input_fingerprint: String,
148 pub now_ms: u64,
149}
150
151#[derive(Debug, Clone, PartialEq, Eq)]
153pub struct CodeRepositorySetRefreshTaskClaimRequest {
154 pub task_id: Option<String>,
155 pub lease_owner: String,
156 pub lease_duration_ms: u64,
157 pub max_attempts: u32,
158 pub now_ms: u64,
159}
160
161#[derive(Debug, Clone, PartialEq, Eq)]
163pub struct CodeRepositorySetRefreshTaskCompletion {
164 pub task_id: String,
165 pub lease_owner: String,
166 pub attempt_count: u32,
167 pub now_ms: u64,
168}
169
170#[derive(Debug, Clone, PartialEq, Eq)]
172pub struct CodeRepositorySetRefreshTaskFailure {
173 pub task_id: String,
174 pub lease_owner: String,
175 pub attempt_count: u32,
176 pub error_kind: String,
177 pub error_message: String,
178 pub retry_backoff_ms: u64,
179 pub max_attempts: u32,
180 pub now_ms: u64,
181}
182
183pub trait CodeRepositoryStore: Send + Sync {
185 fn upsert_code_repository(
186 &self,
187 registration: CodeRepositoryRegistration,
188 ) -> StorageFuture<'_, CodeRepositoryStatus>;
189
190 fn code_repository_status(
191 &self,
192 repository: String,
193 ) -> StorageFuture<'_, Option<CodeRepositoryStatus>>;
194
195 fn list_code_repositories(&self) -> StorageFuture<'_, Vec<CodeRepositoryStatus>> {
196 Box::pin(async { Ok(Vec::new()) })
197 }
198
199 fn remove_code_repository(
200 &self,
201 repository: String,
202 now_ms: u64,
203 ) -> StorageFuture<'_, Option<CodeRepositoryRemovalSummary>> {
204 Box::pin(async move {
205 Err(StorageError::InvalidInput(format!(
206 "code repository removal for '{repository}' at {now_ms} is unavailable"
207 )))
208 })
209 }
210
211 fn code_repository_scope_status(
212 &self,
213 repository: String,
214 resolved_commit_sha: String,
215 path_filters: Vec<String>,
216 language_filters: Vec<String>,
217 ) -> StorageFuture<'_, Option<CodeRepositoryStatus>>;
218
219 fn latest_code_repository_scope_status(
220 &self,
221 _repository: String,
222 _path_filters: Vec<String>,
223 _language_filters: Vec<String>,
224 ) -> StorageFuture<'_, Option<CodeRepositoryStatus>> {
225 Box::pin(async { Ok(None) })
226 }
227
228 fn queue_code_index_task(
229 &self,
230 task: CodeIndexTaskSeed,
231 ) -> StorageFuture<'_, CodeIndexTaskRecord>;
232
233 fn claim_code_index_task(
234 &self,
235 request: CodeIndexTaskClaimRequest,
236 ) -> StorageFuture<'_, Option<CodeIndexTaskRecord>>;
237
238 fn recover_code_index_task_leases(
239 &self,
240 _now_ms: u64,
241 _max_attempts: u32,
242 ) -> StorageFuture<'_, ()> {
243 Box::pin(async {
244 Err(StorageError::InvalidInput(
245 CODE_INDEX_TASK_LEASE_RECOVERY_UNAVAILABLE.to_owned(),
246 ))
247 })
248 }
249
250 fn running_code_index_task_leases(&self) -> StorageFuture<'_, Vec<CodeIndexTaskLeaseRecord>> {
251 Box::pin(async { Ok(Vec::new()) })
252 }
253
254 fn recover_code_index_task_leases_by_task(
255 &self,
256 _request: CodeIndexTaskLeaseRecovery,
257 ) -> StorageFuture<'_, usize> {
258 Box::pin(async {
259 Err(StorageError::InvalidInput(
260 CODE_INDEX_TASK_LEASE_RECOVERY_UNAVAILABLE.to_owned(),
261 ))
262 })
263 }
264
265 fn reset_code_index_tasks(
266 &self,
267 _repository_id: String,
268 _now_ms: u64,
269 ) -> StorageFuture<'_, Vec<CodeIndexTaskRecord>> {
270 Box::pin(async {
271 Err(StorageError::InvalidInput(
272 "code index task reset is unavailable".to_owned(),
273 ))
274 })
275 }
276
277 fn renew_code_index_task_lease(
278 &self,
279 _request: CodeIndexTaskLeaseRenewal,
280 ) -> StorageFuture<'_, CodeIndexTaskRecord> {
281 Box::pin(async {
282 Err(StorageError::InvalidInput(
283 CODE_INDEX_TASK_LEASE_RENEWAL_UNAVAILABLE.to_owned(),
284 ))
285 })
286 }
287
288 fn complete_code_index_task(
289 &self,
290 request: CodeIndexTaskCompletion,
291 ) -> StorageFuture<'_, CodeIndexTaskRecord>;
292
293 fn fail_code_index_task(
294 &self,
295 request: CodeIndexTaskFailure,
296 ) -> StorageFuture<'_, CodeIndexTaskRecord>;
297
298 fn code_index_task(&self, task_id: String) -> StorageFuture<'_, Option<CodeIndexTaskRecord>>;
299
300 fn active_code_index_task(
301 &self,
302 repository_id: String,
303 ) -> StorageFuture<'_, Option<CodeIndexTaskRecord>>;
304
305 fn code_index_task_queue_status(&self) -> StorageFuture<'_, CodeIndexTaskQueueStatus> {
306 Box::pin(async { Ok(CodeIndexTaskQueueStatus::default()) })
307 }
308
309 fn code_index_checkpoint(
310 &self,
311 source_scope: String,
312 ) -> StorageFuture<'_, Option<CodeIndexCheckpoint>>;
313
314 fn latest_code_index_checkpoint(
315 &self,
316 _repository_id: String,
317 ) -> StorageFuture<'_, Option<CodeIndexCheckpoint>> {
318 Box::pin(async { Ok(None) })
319 }
320
321 fn code_scope_retention(
322 &self,
323 repository_id: String,
324 ) -> StorageFuture<'_, CodeScopeRetentionSummary>;
325
326 fn prune_code_repository_scopes(
327 &self,
328 request: CodeScopeRetentionRequest,
329 ) -> StorageFuture<'_, CodeScopeRetentionSummary>;
330
331 fn code_file_fingerprints(
332 &self,
333 repository_id: String,
334 ) -> StorageFuture<'_, Vec<CodeFileFingerprint>>;
335
336 fn code_file_fingerprints_for_scope(
337 &self,
338 source_scope: String,
339 ) -> StorageFuture<'_, Vec<CodeFileFingerprint>> {
340 Box::pin(async move {
341 Err(StorageError::InvalidInput(format!(
342 "code file fingerprints for scope '{source_scope}' are unavailable"
343 )))
344 })
345 }
346
347 fn code_file_fingerprints_for_paths(
348 &self,
349 source_scope: String,
350 paths: Vec<String>,
351 ) -> StorageFuture<'_, Vec<CodeFileFingerprint>> {
352 Box::pin(async move {
353 let mut fingerprints = self.code_file_fingerprints_for_scope(source_scope).await?;
354 fingerprints.retain(|fingerprint| paths.iter().any(|path| path == &fingerprint.path));
355 Ok(fingerprints)
356 })
357 }
358
359 fn code_file_candidate_paths_for_scope(
360 &self,
361 source_scope: String,
362 _path_filters: Vec<String>,
363 _language_filters: Vec<String>,
364 _exclude_generated: bool,
365 _limit: usize,
366 ) -> StorageFuture<'_, Vec<String>> {
367 Box::pin(async move {
368 Err(StorageError::InvalidInput(format!(
369 "bounded code file candidate paths for scope '{source_scope}' are unavailable"
370 )))
371 })
372 }
373
374 fn code_file_candidate_paths_for_query_scope(
375 &self,
376 source_scope: String,
377 _query: String,
378 path_filters: Vec<String>,
379 language_filters: Vec<String>,
380 exclude_generated: bool,
381 limit: usize,
382 ) -> StorageFuture<'_, Vec<String>> {
383 self.code_file_candidate_paths_for_scope(
384 source_scope,
385 path_filters,
386 language_filters,
387 exclude_generated,
388 limit,
389 )
390 }
391
392 fn apply_code_index_snapshot(
393 &self,
394 snapshot: CodeIndexSnapshot,
395 ) -> StorageFuture<'_, CodeIndexSummary>;
396
397 fn clear_code_workspace_state(
398 &self,
399 _repository_id: String,
400 _source_scope: String,
401 ) -> StorageFuture<'_, ()> {
402 Box::pin(async { Ok(()) })
403 }
404
405 fn begin_code_index_session(
406 &self,
407 session: CodeIndexSession,
408 ) -> StorageFuture<'_, CodeIndexCheckpoint> {
409 Box::pin(async move {
410 Err(StorageError::InvalidInput(format!(
411 "checkpointed code index sessions for scope '{}' are unavailable",
412 session.source_scope
413 )))
414 })
415 }
416
417 fn apply_code_index_batch(
418 &self,
419 batch: CodeIndexBatch,
420 ) -> StorageFuture<'_, CodeIndexCheckpoint> {
421 Box::pin(async move {
422 Err(StorageError::InvalidInput(format!(
423 "checkpointed code index batches for scope '{}' are unavailable",
424 batch.source_scope
425 )))
426 })
427 }
428
429 fn finalize_code_index_session(
430 &self,
431 session: CodeIndexSession,
432 ) -> StorageFuture<'_, CodeIndexSummary> {
433 Box::pin(async move {
434 Err(StorageError::InvalidInput(format!(
435 "checkpointed code index finalization for scope '{}' is unavailable",
436 session.source_scope
437 )))
438 })
439 }
440
441 fn search_code(
442 &self,
443 request: CodeRetrievalRequest,
444 ) -> StorageFuture<'_, Vec<CodeRetrievalHit>>;
445
446 fn search_code_feature_flags(
447 &self,
448 request: CodeFeatureFlagRequest,
449 ) -> StorageFuture<'_, Vec<CodeFeatureFlagGraph>> {
450 Box::pin(async move {
451 Err(StorageError::InvalidInput(format!(
452 "code feature flag search for repository '{}' is unavailable",
453 request.repository.repository
454 )))
455 })
456 }
457
458 fn search_code_feature_flags_scope(
459 &self,
460 source_scope: String,
461 _request: CodeFeatureFlagRequest,
462 ) -> StorageFuture<'_, Vec<CodeFeatureFlagGraph>> {
463 Box::pin(async move {
464 Err(StorageError::InvalidInput(format!(
465 "code feature flag search for source scope '{source_scope}' is unavailable"
466 )))
467 })
468 }
469
470 fn search_code_scope(
471 &self,
472 source_scope: String,
473 _request: CodeRetrievalRequest,
474 ) -> StorageFuture<'_, Vec<CodeRetrievalHit>> {
475 Box::pin(async move {
476 Err(StorageError::InvalidInput(format!(
477 "code search for source scope '{source_scope}' is unavailable"
478 )))
479 })
480 }
481
482 fn analyze_code_impact(
483 &self,
484 request: CodeImpactRequest,
485 changes: CodeImpactChanges,
486 ) -> StorageFuture<'_, Vec<CodeRetrievalHit>>;
487
488 fn analyze_code_impact_scope(
489 &self,
490 source_scope: String,
491 _request: CodeImpactRequest,
492 _changes: CodeImpactChanges,
493 ) -> StorageFuture<'_, Vec<CodeRetrievalHit>> {
494 Box::pin(async move {
495 Err(StorageError::InvalidInput(format!(
496 "code impact analysis for source scope '{source_scope}' is unavailable"
497 )))
498 })
499 }
500
501 fn codebase_view_snapshot(
502 &self,
503 source_scope: String,
504 _request: CodebaseViewRequest,
505 _row_limit: usize,
506 ) -> StorageFuture<'_, CodebaseViewSnapshot> {
507 Box::pin(async move {
508 Err(StorageError::InvalidInput(format!(
509 "codebase view snapshot for source scope '{source_scope}' is unavailable"
510 )))
511 })
512 }
513
514 fn code_repository_totals(&self) -> StorageFuture<'_, CodeRepositoryTotals> {
515 Box::pin(async { Ok(CodeRepositoryTotals::default()) })
516 }
517
518 fn code_repository_report(
519 &self,
520 repository: String,
521 ) -> StorageFuture<'_, CodeRepositoryReport> {
522 Box::pin(async move {
523 Err(StorageError::InvalidInput(format!(
524 "code repository report for '{repository}' is unavailable"
525 )))
526 })
527 }
528
529 fn code_repository_scope_symbol_generation_counts(
530 &self,
531 source_scope: String,
532 ) -> StorageFuture<'_, CodeSymbolGenerationCounts> {
533 Box::pin(async move {
534 Err(StorageError::InvalidInput(format!(
535 "code symbol generation counts for source scope '{source_scope}' are unavailable"
536 )))
537 })
538 }
539
540 fn refresh_software_global_projection(
541 &self,
542 source_scope: String,
543 ) -> StorageFuture<'_, SoftwareGlobalProjection> {
544 Box::pin(async move {
545 Err(StorageError::InvalidInput(format!(
546 "software global projection for source scope '{source_scope}' is unavailable"
547 )))
548 })
549 }
550
551 fn software_global_projection(
552 &self,
553 request: SoftwareGlobalRequest,
554 ) -> StorageFuture<'_, SoftwareGlobalProjection> {
555 Box::pin(async move {
556 Err(StorageError::InvalidInput(format!(
557 "software global projection for repository '{}' is unavailable",
558 request.repository.repository
559 )))
560 })
561 }
562
563 fn software_global_projection_for_scope(
564 &self,
565 source_scope: String,
566 _request: SoftwareGlobalRequest,
567 ) -> StorageFuture<'_, SoftwareGlobalProjection> {
568 Box::pin(async move {
569 Err(StorageError::InvalidInput(format!(
570 "software global projection for source scope '{source_scope}' is unavailable"
571 )))
572 })
573 }
574
575 fn create_code_repository_set(
576 &self,
577 _seed: CodeRepositorySetSeed,
578 ) -> StorageFuture<'_, CodeRepositorySet> {
579 Box::pin(async {
580 Err(StorageError::InvalidInput(
581 "repository set storage is unavailable".to_owned(),
582 ))
583 })
584 }
585
586 fn add_code_repository_set_member(
587 &self,
588 _seed: CodeRepositorySetMemberSeed,
589 ) -> StorageFuture<'_, CodeRepositorySetMember> {
590 Box::pin(async {
591 Err(StorageError::InvalidInput(
592 "repository set member storage is unavailable".to_owned(),
593 ))
594 })
595 }
596
597 fn remove_code_repository_set_member(
598 &self,
599 _set_alias: String,
600 _repository_alias: String,
601 ) -> StorageFuture<'_, CodeRepositorySetMember> {
602 Box::pin(async {
603 Err(StorageError::InvalidInput(
604 "repository set member storage is unavailable".to_owned(),
605 ))
606 })
607 }
608
609 fn code_repository_set(
610 &self,
611 _set_alias: String,
612 ) -> StorageFuture<'_, Option<CodeRepositorySet>> {
613 Box::pin(async { Ok(None) })
614 }
615
616 fn code_repository_set_status(
617 &self,
618 _set_alias: String,
619 ) -> StorageFuture<'_, Option<CodeRepositorySetStatus>> {
620 Box::pin(async { Ok(None) })
621 }
622
623 fn refresh_code_repository_set_overlay(
624 &self,
625 _set_alias: String,
626 _now_ms: u64,
627 ) -> StorageFuture<'_, CodeRepositorySetRefreshSummary> {
628 Box::pin(async {
629 Err(StorageError::InvalidInput(
630 "repository set overlay refresh is unavailable".to_owned(),
631 ))
632 })
633 }
634
635 fn code_repository_set_cross_edges(
636 &self,
637 _set_id: String,
638 ) -> StorageFuture<'_, Vec<CodeRepositoryCrossEdge>> {
639 Box::pin(async { Ok(Vec::new()) })
640 }
641
642 fn queue_code_repository_set_refresh_task(
643 &self,
644 _task: CodeRepositorySetRefreshTaskSeed,
645 ) -> StorageFuture<'_, CodeRepositorySetRefreshTaskRecord> {
646 Box::pin(async {
647 Err(StorageError::InvalidInput(
648 "repository set refresh task storage is unavailable".to_owned(),
649 ))
650 })
651 }
652
653 fn claim_code_repository_set_refresh_task(
654 &self,
655 _request: CodeRepositorySetRefreshTaskClaimRequest,
656 ) -> StorageFuture<'_, Option<CodeRepositorySetRefreshTaskRecord>> {
657 Box::pin(async { Ok(None) })
658 }
659
660 fn complete_code_repository_set_refresh_task(
661 &self,
662 _request: CodeRepositorySetRefreshTaskCompletion,
663 ) -> StorageFuture<'_, CodeRepositorySetRefreshTaskRecord> {
664 Box::pin(async {
665 Err(StorageError::InvalidInput(
666 "repository set refresh task storage is unavailable".to_owned(),
667 ))
668 })
669 }
670
671 fn fail_code_repository_set_refresh_task(
672 &self,
673 _request: CodeRepositorySetRefreshTaskFailure,
674 ) -> StorageFuture<'_, CodeRepositorySetRefreshTaskRecord> {
675 Box::pin(async {
676 Err(StorageError::InvalidInput(
677 "repository set refresh task storage is unavailable".to_owned(),
678 ))
679 })
680 }
681}