Skip to main content

trellis_core/
transaction_build.rs

1use crate::{
2    AuditEvent, CollectionContext, CollectionNode, DependencyList, DeriveContext, DeriveError,
3    DerivedNode, GraphResult, InputNode, ScopeId, Transaction,
4};
5use std::collections::{BTreeMap, BTreeSet};
6
7impl<C: 'static, O> Transaction<'_, C, O>
8where
9    O: Clone + PartialEq + 'static,
10{
11    /// Stages creation of a root scope with no parent.
12    pub fn create_scope(&mut self, debug_name: impl Into<String>) -> GraphResult<ScopeId> {
13        self.ensure_open()?;
14        let scope = self.graph.allocate_scope_id();
15        let scope = self
16            .working
17            .create_scope_with_parent_direct(scope, debug_name, None)?;
18        self.graph_mutated = true;
19        self.staged_events.push(AuditEvent::ScopeCreated(scope));
20        Ok(scope)
21    }
22
23    /// Stages creation of a scope with an optional parent.
24    pub fn create_scope_with_parent(
25        &mut self,
26        debug_name: impl Into<String>,
27        parent: Option<ScopeId>,
28    ) -> GraphResult<ScopeId> {
29        self.ensure_open()?;
30        let scope = self.graph.allocate_scope_id();
31        match self
32            .working
33            .create_scope_with_parent_direct(scope, debug_name, parent)
34        {
35            Ok(scope) => {
36                self.graph_mutated = true;
37                self.staged_events.push(AuditEvent::ScopeCreated(scope));
38                Ok(scope)
39            }
40            Err(error) => {
41                self.failed.get_or_insert_with(|| error.clone());
42                Err(error)
43            }
44        }
45    }
46
47    /// Stages closing a scope for resource ownership teardown.
48    pub fn close_scope(&mut self, scope: ScopeId) -> GraphResult<()> {
49        self.ensure_open()?;
50        match self.working.close_scope_direct(scope) {
51            Ok(closed_scopes) => {
52                if !closed_scopes.is_empty() {
53                    self.graph_mutated = true;
54                }
55                self.staged_events
56                    .extend(closed_scopes.into_iter().map(AuditEvent::ScopeClosed));
57                Ok(())
58            }
59            Err(error) => {
60                self.failed.get_or_insert_with(|| error.clone());
61                Err(error)
62            }
63        }
64    }
65
66    /// Stages creation of an input node.
67    pub fn input<T>(&mut self, debug_name: impl Into<String>) -> GraphResult<InputNode<T>>
68    where
69        T: Clone + PartialEq + Send + Sync + 'static,
70    {
71        self.ensure_open()?;
72        let id = self.graph.allocate_node_id();
73        let input = self.working.input_direct(id, debug_name)?;
74        self.graph_mutated = true;
75        self.staged_events.push(AuditEvent::NodeCreated(input.id()));
76        Ok(input)
77    }
78
79    /// Stages creation of a derived node with explicit dependencies.
80    pub fn derived<T>(
81        &mut self,
82        debug_name: impl Into<String>,
83        dependencies: DependencyList,
84        derive: impl for<'ctx> Fn(&DeriveContext<'ctx, C, O>) -> Result<T, DeriveError>
85        + Send
86        + Sync
87        + 'static,
88    ) -> GraphResult<DerivedNode<T>>
89    where
90        T: Clone + PartialEq + Send + Sync + 'static,
91    {
92        self.ensure_open()?;
93        let id = self.graph.allocate_node_id();
94        match self
95            .working
96            .derived_direct(id, debug_name, dependencies, derive)
97        {
98            Ok(derived) => {
99                self.graph_mutated = true;
100                self.staged_events
101                    .push(AuditEvent::NodeCreated(derived.id()));
102                Ok(derived)
103            }
104            Err(error) => {
105                self.failed.get_or_insert_with(|| error.clone());
106                Err(error)
107            }
108        }
109    }
110
111    /// Stages creation of a map collection node with explicit dependencies.
112    pub fn collection<K, V>(
113        &mut self,
114        debug_name: impl Into<String>,
115        dependencies: DependencyList,
116        derive: impl for<'ctx> Fn(&CollectionContext<'ctx, C, O>) -> Result<BTreeMap<K, V>, DeriveError>
117        + Send
118        + Sync
119        + 'static,
120    ) -> GraphResult<CollectionNode<K, V>>
121    where
122        K: Clone + Ord + Send + Sync + 'static,
123        V: Clone + PartialEq + Send + Sync + 'static,
124    {
125        self.map_collection(debug_name, dependencies, derive)
126    }
127
128    /// Stages creation of a map collection node with explicit dependencies.
129    pub fn map_collection<K, V>(
130        &mut self,
131        debug_name: impl Into<String>,
132        dependencies: DependencyList,
133        derive: impl for<'ctx> Fn(&CollectionContext<'ctx, C, O>) -> Result<BTreeMap<K, V>, DeriveError>
134        + Send
135        + Sync
136        + 'static,
137    ) -> GraphResult<CollectionNode<K, V>>
138    where
139        K: Clone + Ord + Send + Sync + 'static,
140        V: Clone + PartialEq + Send + Sync + 'static,
141    {
142        self.ensure_open()?;
143        let id = self.graph.allocate_node_id();
144        match self
145            .working
146            .collection_map_direct(id, debug_name, dependencies, derive)
147        {
148            Ok(collection) => {
149                self.graph_mutated = true;
150                self.staged_events
151                    .push(AuditEvent::NodeCreated(collection.id()));
152                Ok(collection)
153            }
154            Err(error) => {
155                self.failed.get_or_insert_with(|| error.clone());
156                Err(error)
157            }
158        }
159    }
160
161    /// Stages creation of a set collection node with explicit dependencies.
162    pub fn set_collection<K>(
163        &mut self,
164        debug_name: impl Into<String>,
165        dependencies: DependencyList,
166        derive: impl for<'ctx> Fn(&CollectionContext<'ctx, C, O>) -> Result<BTreeSet<K>, DeriveError>
167        + Send
168        + Sync
169        + 'static,
170    ) -> GraphResult<CollectionNode<K, ()>>
171    where
172        K: Clone + Ord + Send + Sync + 'static,
173    {
174        self.ensure_open()?;
175        let id = self.graph.allocate_node_id();
176        match self
177            .working
178            .collection_set_direct(id, debug_name, dependencies, derive)
179        {
180            Ok(collection) => {
181                self.graph_mutated = true;
182                self.staged_events
183                    .push(AuditEvent::NodeCreated(collection.id()));
184                Ok(collection)
185            }
186            Err(error) => {
187                self.failed.get_or_insert_with(|| error.clone());
188                Err(error)
189            }
190        }
191    }
192
193    /// Stages attaching a node to an owning scope.
194    pub fn attach_node_to_scope(
195        &mut self,
196        node: impl crate::NodeHandle,
197        scope: ScopeId,
198    ) -> GraphResult<()> {
199        self.ensure_open()?;
200        let node_id = node.id();
201        match self.working.attach_node_to_scope_direct(node_id, scope) {
202            Ok(()) => {
203                self.graph_mutated = true;
204                self.staged_events.push(AuditEvent::NodeAttached {
205                    node: node_id,
206                    scope,
207                });
208                Ok(())
209            }
210            Err(error) => {
211                self.failed.get_or_insert_with(|| error.clone());
212                Err(error)
213            }
214        }
215    }
216}