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