Skip to main content

relay_knowledge/application/code_repository/repository_graph/
mod.rs

1//! Builds bounded OKF neighborhoods from one indexed repository snapshot.
2
3use crate::{
4    api::{
5        ApiError, ApiMetadata, CodeRepositoryScopeMetadata, RepositoryGraphNeighborhoodResponseV1,
6        RequestContext,
7    },
8    application::service::RelayKnowledgeService,
9    domain::{RepositoryGraphNeighborhoodRequest, project_okf_neighborhood},
10};
11
12use super::{
13    blocking::run_blocking_domain,
14    errors::storage_api_error,
15    repository::required_code_repository,
16    scope::{
17        indexed_commit_for_selector, indexed_source_scope, missing_indexed_source_scope_error,
18        resolved_code_scope_status,
19    },
20};
21
22const MAX_OKF_DOCUMENTS: usize = 2_048;
23const MAX_OKF_DOCUMENT_BYTES: usize = 8 * 1_024 * 1_024;
24
25impl RelayKnowledgeService {
26    /// Returns an OKF concept/source neighborhood from a fresh indexed repository snapshot.
27    pub async fn repository_graph_neighborhood(
28        &self,
29        mut request: RepositoryGraphNeighborhoodRequest,
30        context: RequestContext,
31    ) -> Result<RepositoryGraphNeighborhoodResponseV1, ApiError> {
32        let store = self.store().await.map_err(storage_api_error)?;
33        let status =
34            required_code_repository(store.as_ref(), &request.repository.repository).await?;
35        let requested_ref = request.repository.ref_selector.clone();
36        request.repository.ref_selector = indexed_commit_for_selector(
37            &status,
38            &request.repository,
39            request.repository.ref_selector.clone(),
40        )
41        .await?;
42        let scoped_status =
43            resolved_code_scope_status(&store, &status, &request.repository).await?;
44        if scoped_status.stale {
45            return Err(ApiError::invalid_argument(format!(
46                "code repository '{}' graph scope is stale; refresh the index before requesting a neighborhood",
47                scoped_status.alias
48            )));
49        }
50        let source_scope = indexed_source_scope(&scoped_status)
51            .ok_or_else(|| missing_indexed_source_scope_error(&scoped_status))?;
52        let documents = store
53            .repository_documents_for_scope(
54                source_scope,
55                request.repository.path_filters.clone(),
56                MAX_OKF_DOCUMENTS,
57                MAX_OKF_DOCUMENT_BYTES,
58            )
59            .await
60            .map_err(storage_api_error)?;
61        let projection_request = request.clone();
62        let neighborhood =
63            run_blocking_domain(move || project_okf_neighborhood(&documents, &projection_request))
64                .await?;
65        let graph_version = store
66            .current_graph_version()
67            .await
68            .map_err(storage_api_error)?;
69
70        Ok(RepositoryGraphNeighborhoodResponseV1 {
71            schema_version: 1,
72            metadata: ApiMetadata::graph_only(&context, graph_version),
73            scope: CodeRepositoryScopeMetadata::from_status(
74                &scoped_status,
75                &request.repository,
76                requested_ref,
77            ),
78            request,
79            nodes: neighborhood.nodes,
80            edges: neighborhood.edges,
81            truncated: neighborhood.truncated,
82        })
83    }
84}
85
86#[cfg(test)]
87#[path = "mod_tests.rs"]
88mod tests;