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 + '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> + 'static,
85    ) -> GraphResult<DerivedNode<T>>
86    where
87        T: Clone + PartialEq + 'static,
88    {
89        self.ensure_open()?;
90        let id = self.graph.allocate_node_id();
91        match self
92            .working
93            .derived_direct(id, debug_name, dependencies, derive)
94        {
95            Ok(derived) => {
96                self.graph_mutated = true;
97                self.staged_events
98                    .push(AuditEvent::NodeCreated(derived.id()));
99                Ok(derived)
100            }
101            Err(error) => {
102                self.failed.get_or_insert_with(|| error.clone());
103                Err(error)
104            }
105        }
106    }
107
108    /// Stages creation of a map collection node with explicit dependencies.
109    pub fn collection<K, V>(
110        &mut self,
111        debug_name: impl Into<String>,
112        dependencies: DependencyList,
113        derive: impl for<'ctx> Fn(&CollectionContext<'ctx, C, O>) -> Result<BTreeMap<K, V>, DeriveError>
114        + 'static,
115    ) -> GraphResult<CollectionNode<K, V>>
116    where
117        K: Clone + Ord + 'static,
118        V: Clone + PartialEq + 'static,
119    {
120        self.map_collection(debug_name, dependencies, derive)
121    }
122
123    /// Stages creation of a map collection node with explicit dependencies.
124    pub fn map_collection<K, V>(
125        &mut self,
126        debug_name: impl Into<String>,
127        dependencies: DependencyList,
128        derive: impl for<'ctx> Fn(&CollectionContext<'ctx, C, O>) -> Result<BTreeMap<K, V>, DeriveError>
129        + 'static,
130    ) -> GraphResult<CollectionNode<K, V>>
131    where
132        K: Clone + Ord + 'static,
133        V: Clone + PartialEq + 'static,
134    {
135        self.ensure_open()?;
136        let id = self.graph.allocate_node_id();
137        match self
138            .working
139            .collection_map_direct(id, debug_name, dependencies, derive)
140        {
141            Ok(collection) => {
142                self.graph_mutated = true;
143                self.staged_events
144                    .push(AuditEvent::NodeCreated(collection.id()));
145                Ok(collection)
146            }
147            Err(error) => {
148                self.failed.get_or_insert_with(|| error.clone());
149                Err(error)
150            }
151        }
152    }
153
154    /// Stages creation of a set collection node with explicit dependencies.
155    pub fn set_collection<K>(
156        &mut self,
157        debug_name: impl Into<String>,
158        dependencies: DependencyList,
159        derive: impl for<'ctx> Fn(&CollectionContext<'ctx, C, O>) -> Result<BTreeSet<K>, DeriveError>
160        + 'static,
161    ) -> GraphResult<CollectionNode<K, ()>>
162    where
163        K: Clone + Ord + 'static,
164    {
165        self.ensure_open()?;
166        let id = self.graph.allocate_node_id();
167        match self
168            .working
169            .collection_set_direct(id, debug_name, dependencies, derive)
170        {
171            Ok(collection) => {
172                self.graph_mutated = true;
173                self.staged_events
174                    .push(AuditEvent::NodeCreated(collection.id()));
175                Ok(collection)
176            }
177            Err(error) => {
178                self.failed.get_or_insert_with(|| error.clone());
179                Err(error)
180            }
181        }
182    }
183
184    /// Stages attaching a node to an owning scope.
185    pub fn attach_node_to_scope(
186        &mut self,
187        node: impl crate::NodeHandle,
188        scope: ScopeId,
189    ) -> GraphResult<()> {
190        self.ensure_open()?;
191        let node_id = node.id();
192        match self.working.attach_node_to_scope_direct(node_id, scope) {
193            Ok(()) => {
194                self.graph_mutated = true;
195                self.staged_events.push(AuditEvent::NodeAttached {
196                    node: node_id,
197                    scope,
198                });
199                Ok(())
200            }
201            Err(error) => {
202                self.failed.get_or_insert_with(|| error.clone());
203                Err(error)
204            }
205        }
206    }
207}