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