Skip to main content

relay_knowledge/storage/contracts/
code.rs

1//! Storage contracts for code repository indexes.
2
3use crate::domain::CodeIndexSummary;
4
5use super::{FrameworkGraphStore, StorageError};
6
7mod catalog;
8mod projection;
9mod publication;
10mod query;
11mod repository_set;
12mod retention;
13mod source;
14mod task;
15
16pub use catalog::RepositoryCatalogStore;
17pub use projection::SoftwareProjectionStore;
18pub use publication::CodeIndexPublicationStore;
19pub use query::CodeQueryReadStore;
20pub use repository_set::CodeRepositorySetStore;
21pub use retention::CodeScopeRetentionStore;
22pub use source::CodeIndexSourceStore;
23pub use task::CodeIndexTaskStore;
24
25/// Default error text for stores that do not support code task lease recovery.
26pub const CODE_INDEX_TASK_LEASE_RECOVERY_UNAVAILABLE: &str =
27    "code index task lease recovery is unavailable";
28
29/// Default error text for stores that do not support code task lease renewal.
30pub const CODE_INDEX_TASK_LEASE_RENEWAL_UNAVAILABLE: &str =
31    "code index task lease renewal is unavailable";
32
33/// Stable coarse states in the durable code-index finalization plan.
34pub const CODE_INDEX_FINALIZATION_COARSE_PHASE_COUNT: usize = 11;
35
36/// Hard bound for missing index units, coarse phases, and terminal observation.
37pub const CODE_INDEX_FINALIZATION_MAX_STEPS: usize = crate::domain::CODE_QUERY_INDEX_PLAN_UNIT_COUNT
38    + CODE_INDEX_FINALIZATION_COARSE_PHASE_COUNT
39    + 2;
40
41/// Derives the hard finalization quantum bound including worst-case
42/// byte-limited reference resolution plus reference-search cleanup, group
43/// discovery, and build pages.
44pub fn code_index_finalization_max_steps(
45    committed_reference_count: usize,
46) -> Result<usize, StorageError> {
47    committed_reference_count
48        .checked_mul(4)
49        .and_then(|pages| pages.checked_add(CODE_INDEX_FINALIZATION_MAX_STEPS + 6))
50        .ok_or_else(|| {
51            StorageError::CapacityExceeded(
52                "reference-resolution and search finalization step bound exceeds platform capacity"
53                    .to_owned(),
54            )
55        })
56}
57
58/// Result of advancing one durable code-index finalization writer quantum.
59#[derive(Debug, Clone, PartialEq, Eq)]
60pub enum CodeIndexFinalizationStep {
61    Pending { checkpoint_state: String },
62    Ready(Box<CodeIndexSummary>),
63}
64
65/// Diff-derived inputs used to seed code impact expansion.
66#[derive(Debug, Clone, Default, PartialEq, Eq)]
67pub struct CodeImpactChanges {
68    pub paths: Vec<String>,
69    pub deleted_symbol_names: Vec<String>,
70}
71
72/// Bounded repository-set overlay keys needed to decorate retrieval candidates.
73#[derive(Debug, Clone, Default, PartialEq, Eq)]
74pub struct CodeRepositorySetEdgeSelector {
75    pub origin_files: Vec<(String, String)>,
76    pub target_records: Vec<(String, String, String)>,
77}
78
79/// New background code index task to persist or deduplicate.
80#[derive(Debug, Clone, PartialEq, Eq)]
81pub struct CodeIndexTaskSeed {
82    pub repository_id: String,
83    pub alias: String,
84    pub ref_selector: String,
85    pub resolved_commit_sha: String,
86    pub tree_hash: String,
87    pub source_scope: String,
88    pub path_filters: Vec<String>,
89    pub language_filters: Vec<String>,
90    pub mode: crate::domain::CodeIndexMode,
91    pub input_fingerprint: String,
92    pub resource_budget: crate::domain::CodeIndexResourceBudget,
93    pub payload_json: String,
94    pub now_ms: u64,
95}
96
97/// Lease acquisition request for one background code index task.
98///
99/// `now_ms` is a caller observation. Storage samples authoritative execution
100/// time only after obtaining its writer lock and rejects future observations.
101#[derive(Debug, Clone, PartialEq, Eq)]
102pub struct CodeIndexTaskClaimRequest {
103    pub task_id: Option<String>,
104    pub lease_owner: String,
105    pub lease_duration_ms: u64,
106    pub max_attempts: u32,
107    pub now_ms: u64,
108}
109
110/// Strict renewal request for one still-live fenced code-index attempt.
111///
112/// Expiry is irrevocable. `now_ms` is only the caller's observation; storage
113/// samples authoritative time after acquiring its writer lock.
114#[derive(Debug, Clone, PartialEq, Eq)]
115pub struct CodeIndexTaskLeaseRenewal {
116    pub task_id: String,
117    pub lease_owner: String,
118    pub attempt_count: u32,
119    pub publication_generation: u64,
120    pub lease_duration_ms: u64,
121    /// Caller-observed time used only to reject future/rollback observations.
122    /// Storage samples authoritative time after obtaining its writer lock.
123    pub now_ms: u64,
124}
125
126/// Active code-index task lease used by service startup recovery.
127#[derive(Debug, Clone, PartialEq, Eq)]
128pub struct CodeIndexTaskLeaseRecord {
129    pub task_id: String,
130    pub lease_owner: String,
131    pub lease_expires_at_ms: Option<u64>,
132    pub attempt_count: u32,
133    pub publication_generation: u64,
134}
135
136/// Durable task target whose already-complete publication may be adopted by
137/// a later fenced attempt without rebuilding code or software facts.
138#[derive(Debug, Clone, PartialEq, Eq)]
139pub struct CodeIndexPublicationTarget {
140    pub task_id: String,
141    pub repository_id: String,
142    pub source_scope: String,
143    pub resolved_commit_sha: String,
144    pub tree_hash: String,
145    pub path_filters: Vec<String>,
146    pub language_filters: Vec<String>,
147}
148
149/// Recovery request carrying the exact running leases observed as orphaned.
150#[derive(Debug, Clone, PartialEq, Eq)]
151pub struct CodeIndexTaskLeaseRecovery {
152    pub leases: Vec<CodeIndexTaskLeaseRecord>,
153    pub now_ms: u64,
154    pub max_attempts: u32,
155    pub error_kind: String,
156    pub error_message: String,
157}
158
159/// Completion report guarded by task lease and attempt token.
160///
161/// Expiry is irrevocable. `now_ms` is only the caller's observation; storage
162/// samples authoritative time after acquiring its writer lock.
163#[derive(Debug, Clone, PartialEq, Eq)]
164pub struct CodeIndexTaskCompletion {
165    pub task_id: String,
166    pub lease_owner: String,
167    pub attempt_count: u32,
168    pub publication_generation: u64,
169    pub now_ms: u64,
170}
171
172/// Failure report for retry and dead-letter handling.
173///
174/// Expiry is irrevocable. `now_ms` is only the caller's observation; storage
175/// samples authoritative time after acquiring its writer lock.
176#[derive(Debug, Clone, PartialEq, Eq)]
177pub struct CodeIndexTaskFailure {
178    pub task_id: String,
179    pub lease_owner: String,
180    pub attempt_count: u32,
181    pub publication_generation: u64,
182    pub error_kind: String,
183    pub error_message: String,
184    pub retry_backoff_ms: u64,
185    pub max_attempts: u32,
186    pub now_ms: u64,
187}
188
189/// Scope retention request after a repository index completes.
190#[derive(Debug, Clone, PartialEq, Eq)]
191pub struct CodeScopeRetentionRequest {
192    pub repository_id: String,
193    pub active_scope: String,
194    pub retain_recent_successful_scopes: usize,
195    /// Whole-repository wall-clock cutoff used for legacy publications and checkpoints.
196    pub repository_retention_cutoff_ms: Option<u64>,
197    /// Publication generation current when whole-repository retention was scheduled.
198    /// Newer generations remain protected even when timestamps share one millisecond.
199    pub repository_retention_cutoff_generation: Option<u64>,
200    /// Scope that was current when whole-repository retention was scheduled.
201    pub repository_retention_initial_scope: Option<String>,
202}
203
204/// New repository set metadata to persist.
205#[derive(Debug, Clone, PartialEq, Eq)]
206pub struct CodeRepositorySetSeed {
207    pub alias: String,
208    pub description: Option<String>,
209    pub default_ref_policy_json: String,
210    pub now_ms: u64,
211}
212
213/// New or replaced repository-set member pointer.
214#[derive(Debug, Clone, PartialEq, Eq)]
215pub struct CodeRepositorySetMemberSeed {
216    pub set_alias: String,
217    pub repository_id: String,
218    pub repository_alias: String,
219    pub ref_selector: String,
220    pub resolved_commit_sha: String,
221    pub source_scope: String,
222    pub path_filters: Vec<String>,
223    pub language_filters: Vec<String>,
224    pub priority: i32,
225}
226
227/// Repository-set overlay refresh task to persist or deduplicate.
228#[derive(Debug, Clone, PartialEq, Eq)]
229pub struct CodeRepositorySetRefreshTaskSeed {
230    pub set_id: String,
231    pub set_alias: String,
232    pub input_fingerprint: String,
233    pub now_ms: u64,
234}
235
236/// Lease acquisition request for one repository-set overlay task.
237#[derive(Debug, Clone, PartialEq, Eq)]
238pub struct CodeRepositorySetRefreshTaskClaimRequest {
239    pub task_id: Option<String>,
240    pub lease_owner: String,
241    pub lease_duration_ms: u64,
242    pub max_attempts: u32,
243    pub now_ms: u64,
244}
245
246/// Attempt-scoped authority required to publish a repository-set overlay.
247///
248/// Storage implementations must validate every field against a live running
249/// task in the same transaction that replaces the overlay rows. A worker that
250/// loses its lease or is superseded by a later attempt therefore cannot publish
251/// a stale DELETE/INSERT sequence.
252#[derive(Debug, Clone, PartialEq, Eq)]
253pub struct CodeRepositorySetRefreshPublication {
254    pub task_id: String,
255    pub set_id: String,
256    pub lease_owner: String,
257    pub attempt_count: u32,
258    pub member_replacements: Vec<CodeRepositorySetMemberSeed>,
259}
260
261/// Completion report guarded by task lease and attempt token.
262#[derive(Debug, Clone, PartialEq, Eq)]
263pub struct CodeRepositorySetRefreshTaskCompletion {
264    pub task_id: String,
265    pub lease_owner: String,
266    pub attempt_count: u32,
267    pub now_ms: u64,
268}
269
270/// Failure report for retry and dead-letter handling.
271#[derive(Debug, Clone, PartialEq, Eq)]
272pub struct CodeRepositorySetRefreshTaskFailure {
273    pub task_id: String,
274    pub lease_owner: String,
275    pub attempt_count: u32,
276    pub error_kind: String,
277    pub error_message: String,
278    pub retry_backoff_ms: u64,
279    pub max_attempts: u32,
280    pub now_ms: u64,
281}
282
283/// Compatibility facade that combines all persisted code repository
284/// capabilities. New workflows depend on the narrow capability they consume.
285pub trait CodeRepositoryStore:
286    FrameworkGraphStore
287    + RepositoryCatalogStore
288    + CodeIndexTaskStore
289    + CodeScopeRetentionStore
290    + CodeIndexSourceStore
291    + CodeIndexPublicationStore
292    + CodeQueryReadStore
293    + SoftwareProjectionStore
294    + CodeRepositorySetStore
295{
296}
297
298impl<T> CodeRepositoryStore for T where
299    T: FrameworkGraphStore
300        + RepositoryCatalogStore
301        + CodeIndexTaskStore
302        + CodeScopeRetentionStore
303        + CodeIndexSourceStore
304        + CodeIndexPublicationStore
305        + CodeQueryReadStore
306        + SoftwareProjectionStore
307        + CodeRepositorySetStore
308        + ?Sized
309{
310}
311
312#[cfg(test)]
313#[path = "code_tests.rs"]
314mod tests;