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