kmp-application 0.1.6

Application services of the KMP kernel: the use cases behind ingest, wake, ask, near, rewind and trace
Documentation
use kmp_domain::{
    GraphNeighborhoodReader, KmpBundle, NodeDetailReader, SnapshotSaveOptions, SnapshotStore,
};

use crate::ApplicationError;
pub use crate::queries::render_graph_bundle::RenderedContext;
use crate::queries::{
    ContextRenderOptions, QueryApplicationService, QueryTimingBreakdown, RehydrateSessionUseCase,
    clamp_native_graph_traversal_depth, render_graph_bundle_with_options,
};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GetContextQuery {
    pub root_node_id: String,
    pub role: String,
    pub depth: u32,
    pub requested_scopes: Vec<String>,
    pub render_options: ContextRenderOptions,
}

#[derive(Debug, Clone, PartialEq)]
pub struct GetContextResult {
    pub bundle: KmpBundle,
    pub rendered: RenderedContext,
    pub requested_scopes: Vec<String>,
    pub served_at: std::time::SystemTime,
    pub timing: Option<QueryTimingBreakdown>,
}

#[derive(Debug)]
pub struct GetContextUseCase<G, D, S> {
    rehydrate_session: RehydrateSessionUseCase<G, D, S>,
}

impl<G, D, S> GetContextUseCase<G, D, S>
where
    G: GraphNeighborhoodReader + Send + Sync,
    D: NodeDetailReader + Send + Sync,
    S: SnapshotStore + Send + Sync,
{
    pub fn new(rehydrate_session: RehydrateSessionUseCase<G, D, S>) -> Self {
        Self { rehydrate_session }
    }

    pub async fn execute(
        &self,
        root_node_id: &str,
        role: &str,
        depth: u32,
        requested_scopes: &[String],
        render_options: &ContextRenderOptions,
    ) -> Result<GetContextResult, ApplicationError> {
        let (bundle, timing) = self
            .rehydrate_session
            .execute_with_depth(
                root_node_id,
                role,
                clamp_native_graph_traversal_depth(depth),
                false,
                SnapshotSaveOptions::default(),
            )
            .await?;
        let rendered = render_graph_bundle_with_options(&bundle, render_options);

        Ok(GetContextResult {
            bundle,
            rendered,
            requested_scopes: requested_scopes.to_vec(),
            served_at: std::time::SystemTime::now(),
            timing: Some(timing),
        })
    }
}

impl<G, D, S> QueryApplicationService<G, D, S>
where
    G: GraphNeighborhoodReader + Send + Sync,
    D: NodeDetailReader + Send + Sync,
    S: SnapshotStore + Send + Sync,
{
    pub async fn get_context(
        &self,
        query: GetContextQuery,
    ) -> Result<GetContextResult, ApplicationError> {
        let rehydrate = RehydrateSessionUseCase::new(
            std::sync::Arc::clone(&self.graph_reader),
            std::sync::Arc::clone(&self.detail_reader),
            std::sync::Arc::clone(&self.snapshot_store),
            self.generator_version,
        );

        GetContextUseCase::new(rehydrate)
            .execute(
                &query.root_node_id,
                &query.role,
                query.depth,
                &query.requested_scopes,
                &query.render_options,
            )
            .await
    }
}