1use std::sync::Arc;
10
11use async_trait::async_trait;
12
13use cognis_core::{Result, Runnable};
14
15use crate::compiled::CompiledGraph;
16use crate::goto::Goto;
17use crate::node::{Node, NodeCtx, NodeOut};
18use crate::state::GraphState;
19
20#[allow(clippy::type_complexity)]
23pub struct Subgraph<P, C>
24where
25 P: GraphState,
26 C: GraphState + Clone,
27 <C as GraphState>::Update: Clone,
28{
29 name: String,
30 child: CompiledGraph<C>,
31 project_in: Arc<dyn Fn(&P) -> C + Send + Sync>,
32 project_out: Arc<dyn Fn(&C) -> P::Update + Send + Sync>,
33 next: Goto,
34}
35
36impl<P, C> Subgraph<P, C>
37where
38 P: GraphState,
39 C: GraphState + Clone + Send + 'static,
40 <C as GraphState>::Update: Clone,
41{
42 pub fn new(
48 name: impl Into<String>,
49 child: CompiledGraph<C>,
50 project_in: impl Fn(&P) -> C + Send + Sync + 'static,
51 project_out: impl Fn(&C) -> P::Update + Send + Sync + 'static,
52 next: Goto,
53 ) -> Self {
54 Self {
55 name: name.into(),
56 child,
57 project_in: Arc::new(project_in),
58 project_out: Arc::new(project_out),
59 next,
60 }
61 }
62}
63
64#[async_trait]
65impl<P, C> Node<P> for Subgraph<P, C>
66where
67 P: GraphState + Send + Sync + 'static,
68 C: GraphState + Clone + Send + Sync + 'static,
69 <C as GraphState>::Update: Clone,
70 <P as GraphState>::Update: Send + 'static,
71{
72 async fn execute(&self, parent: &P, ctx: &NodeCtx<'_>) -> Result<NodeOut<P>> {
73 let seed = (self.project_in)(parent);
74 let mut cfg = ctx.config.clone();
75 cfg.run_id = uuid::Uuid::new_v4();
77 let final_child = self.child.invoke(seed, cfg).await?;
78 let update = (self.project_out)(&final_child);
79 Ok(NodeOut {
80 update,
81 goto: self.next.clone(),
82 })
83 }
84 fn name(&self) -> &str {
85 &self.name
86 }
87}