jellyflow_runtime/runtime/store/
mod.rs1mod dispatch;
10mod dispatch_profile;
11mod events;
12mod history;
13mod snapshot;
14mod subscriptions;
15mod view;
16
17use std::cell::RefCell;
18
19use crate::io::{
20 NodeGraphEditorConfig, NodeGraphInteractionConfig, NodeGraphRuntimeTuning, NodeGraphViewState,
21};
22use crate::profile::{ApplyPipelineError, GraphProfile};
23use crate::runtime::commit::NodeGraphPatch;
24use crate::runtime::lookups::NodeGraphLookups;
25use crate::runtime::middleware::NodeGraphStoreMiddleware;
26use crate::runtime::query::spatial::SpatialQueryCache;
27use jellyflow_core::core::Graph;
28use jellyflow_core::ops::{GraphHistory, GraphMutationFootprint, GraphTransaction};
29
30#[derive(Debug, Clone)]
32pub struct DispatchOutcome {
33 patch: NodeGraphPatch,
35}
36
37impl DispatchOutcome {
38 pub fn new(patch: NodeGraphPatch) -> Self {
39 Self { patch }
40 }
41
42 pub fn from_committed(committed: GraphTransaction) -> Self {
43 Self::new(NodeGraphPatch::new(committed))
44 }
45
46 pub fn patch(&self) -> &NodeGraphPatch {
47 &self.patch
48 }
49
50 pub fn committed(&self) -> &GraphTransaction {
51 self.patch.transaction()
52 }
53
54 pub fn footprint(&self) -> &GraphMutationFootprint {
55 self.patch.footprint()
56 }
57
58 pub fn into_patch(self) -> NodeGraphPatch {
59 self.patch
60 }
61}
62
63#[derive(Debug, thiserror::Error)]
64pub enum DispatchError {
65 #[error(transparent)]
66 Apply(#[from] ApplyPipelineError),
67}
68
69pub struct NodeGraphStore {
73 graph: Graph,
74 graph_revision: u64,
75 layout_facts_revision: u64,
76 view_state: NodeGraphViewState,
77 interaction: NodeGraphInteractionConfig,
78 runtime_tuning: NodeGraphRuntimeTuning,
79 history: GraphHistory,
80 profile: Option<Box<dyn GraphProfile>>,
81 middleware: Option<Box<dyn NodeGraphStoreMiddleware>>,
82 lookups: NodeGraphLookups,
83 spatial_query_cache: RefCell<SpatialQueryCache>,
84 subscriptions: subscriptions::StoreSubscriptions,
85}
86
87impl std::fmt::Debug for NodeGraphStore {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 f.debug_struct("NodeGraphStore")
90 .field("graph_id", &self.graph.graph_id())
91 .field("graph_revision", &self.graph_revision)
92 .field("layout_facts_revision", &self.layout_facts_revision)
93 .field("node_count", &self.graph.nodes().len())
94 .field("edge_count", &self.graph.edges().len())
95 .field("lookup_node_count", &self.lookups.node_count())
96 .field("lookup_edge_count", &self.lookups.edge_count())
97 .field("undo_len", &self.history.undo_len())
98 .field("redo_len", &self.history.redo_len())
99 .field("has_profile", &self.profile.is_some())
100 .field(
101 "event_subscription_count",
102 &self.subscriptions.event_subscription_count(),
103 )
104 .field(
105 "gesture_subscription_count",
106 &self.subscriptions.gesture_subscription_count(),
107 )
108 .field(
109 "selector_subscription_count",
110 &self.subscriptions.selector_subscription_count(),
111 )
112 .finish()
113 }
114}
115
116impl NodeGraphStore {
117 pub fn new(
119 graph: Graph,
120 view_state: NodeGraphViewState,
121 editor_config: NodeGraphEditorConfig,
122 ) -> Self {
123 Self::new_with_optional_profile(graph, view_state, editor_config, None)
124 }
125
126 pub fn with_profile(
128 graph: Graph,
129 view_state: NodeGraphViewState,
130 editor_config: NodeGraphEditorConfig,
131 profile: Box<dyn GraphProfile>,
132 ) -> Self {
133 Self::new_with_optional_profile(graph, view_state, editor_config, Some(profile))
134 }
135
136 fn new_with_optional_profile(
137 graph: Graph,
138 mut view_state: NodeGraphViewState,
139 editor_config: NodeGraphEditorConfig,
140 profile: Option<Box<dyn GraphProfile>>,
141 ) -> Self {
142 view_state.sanitize_for_graph(&graph);
143 let mut lookups = NodeGraphLookups::default();
144 lookups.rebuild_from(&graph);
145 let (interaction, runtime_tuning) = editor_config.into_parts();
146 Self {
147 graph,
148 graph_revision: 0,
149 layout_facts_revision: 0,
150 view_state,
151 interaction,
152 runtime_tuning,
153 history: GraphHistory::default(),
154 profile,
155 middleware: None,
156 lookups,
157 spatial_query_cache: RefCell::new(SpatialQueryCache::default()),
158 subscriptions: subscriptions::StoreSubscriptions::default(),
159 }
160 }
161
162 pub(crate) fn spatial_query_cache(&self) -> &RefCell<SpatialQueryCache> {
163 &self.spatial_query_cache
164 }
165
166 pub fn with_middleware(mut self, middleware: impl NodeGraphStoreMiddleware) -> Self {
167 self.middleware = Some(Box::new(middleware));
168 self
169 }
170}