kmp_application/queries/
get_context.rs1use kmp_domain::{
2 GraphNeighborhoodReader, KmpBundle, NodeDetailReader, SnapshotSaveOptions, SnapshotStore,
3};
4
5use crate::ApplicationError;
6pub use crate::queries::render_graph_bundle::RenderedContext;
7use crate::queries::{
8 ContextRenderOptions, QueryApplicationService, QueryTimingBreakdown, RehydrateSessionUseCase,
9 clamp_native_graph_traversal_depth, render_graph_bundle_with_options,
10};
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct GetContextQuery {
14 pub root_node_id: String,
15 pub role: String,
16 pub depth: u32,
17 pub requested_scopes: Vec<String>,
18 pub render_options: ContextRenderOptions,
19}
20
21#[derive(Debug, Clone, PartialEq)]
22pub struct GetContextResult {
23 pub bundle: KmpBundle,
24 pub rendered: RenderedContext,
25 pub requested_scopes: Vec<String>,
26 pub served_at: std::time::SystemTime,
27 pub timing: Option<QueryTimingBreakdown>,
28}
29
30#[derive(Debug)]
31pub struct GetContextUseCase<G, D, S> {
32 rehydrate_session: RehydrateSessionUseCase<G, D, S>,
33}
34
35impl<G, D, S> GetContextUseCase<G, D, S>
36where
37 G: GraphNeighborhoodReader + Send + Sync,
38 D: NodeDetailReader + Send + Sync,
39 S: SnapshotStore + Send + Sync,
40{
41 pub fn new(rehydrate_session: RehydrateSessionUseCase<G, D, S>) -> Self {
42 Self { rehydrate_session }
43 }
44
45 pub async fn execute(
46 &self,
47 root_node_id: &str,
48 role: &str,
49 depth: u32,
50 requested_scopes: &[String],
51 render_options: &ContextRenderOptions,
52 ) -> Result<GetContextResult, ApplicationError> {
53 let (bundle, timing) = self
54 .rehydrate_session
55 .execute_with_depth(
56 root_node_id,
57 role,
58 clamp_native_graph_traversal_depth(depth),
59 false,
60 SnapshotSaveOptions::default(),
61 )
62 .await?;
63 let rendered = render_graph_bundle_with_options(&bundle, render_options);
64
65 Ok(GetContextResult {
66 bundle,
67 rendered,
68 requested_scopes: requested_scopes.to_vec(),
69 served_at: std::time::SystemTime::now(),
70 timing: Some(timing),
71 })
72 }
73}
74
75impl<G, D, S> QueryApplicationService<G, D, S>
76where
77 G: GraphNeighborhoodReader + Send + Sync,
78 D: NodeDetailReader + Send + Sync,
79 S: SnapshotStore + Send + Sync,
80{
81 pub async fn get_context(
82 &self,
83 query: GetContextQuery,
84 ) -> Result<GetContextResult, ApplicationError> {
85 let rehydrate = RehydrateSessionUseCase::new(
86 std::sync::Arc::clone(&self.graph_reader),
87 std::sync::Arc::clone(&self.detail_reader),
88 std::sync::Arc::clone(&self.snapshot_store),
89 self.generator_version,
90 );
91
92 GetContextUseCase::new(rehydrate)
93 .execute(
94 &query.root_node_id,
95 &query.role,
96 query.depth,
97 &query.requested_scopes,
98 &query.render_options,
99 )
100 .await
101 }
102}