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