postproject_core/storage.rs
1//! Domain-shaped contracts implemented by persistence backends.
2
3use crate::{
4 Activity, Asset, AssetId, ExternalIdentifier, IdentifierScheme, Locator, MediaRoot,
5 MetadataAssertion, MetadataMatch, MetadataProperty, MetadataValue, ObjectRef,
6 OriginalMediaImport, Production, Representation, RepresentationId, RepresentationImport,
7 Resource, ResourceId, Result, Revision, RevisionContext, RevisionEvent, RevisionId,
8 TransactionId, TransactionState,
9};
10
11/// Read operations required from a production persistence backend.
12///
13/// The contract returns domain values and deliberately contains no generic CRUD,
14/// query language, connection, or database-row concepts.
15pub trait ProductionRead {
16 /// Returns the loaded production metadata and configured media roots.
17 fn production(&self) -> &Production;
18
19 /// Loads all assets in deterministic order.
20 ///
21 /// # Errors
22 ///
23 /// Returns a storage-domain error when persisted data cannot be read or
24 /// decoded safely.
25 fn assets(&self) -> Result<Vec<Asset>>;
26
27 /// Loads every representation belonging to an asset in deterministic order.
28 ///
29 /// # Errors
30 ///
31 /// Returns a storage-domain error when persisted data cannot be read or
32 /// decoded safely.
33 fn representations(&self, asset_id: AssetId) -> Result<Vec<Representation>>;
34
35 /// Loads resources used by a representation in structural order.
36 ///
37 /// # Errors
38 ///
39 /// Returns a storage-domain error when persisted data cannot be read or
40 /// decoded safely.
41 fn resources(&self, representation_id: RepresentationId) -> Result<Vec<Resource>>;
42
43 /// Loads every known locator belonging to a resource.
44 ///
45 /// # Errors
46 ///
47 /// Returns a storage-domain error when persisted data cannot be read or
48 /// decoded safely.
49 fn locators(&self, resource_id: ResourceId) -> Result<Vec<Locator>>;
50
51 /// Loads external identifiers attached to `target` in deterministic order.
52 ///
53 /// # Errors
54 ///
55 /// Returns a storage-domain error when persisted data cannot be read or
56 /// decoded safely, or when the target kind is not supported.
57 fn external_identifiers(&self, target: ObjectRef) -> Result<Vec<ExternalIdentifier>>;
58
59 /// Finds objects carrying the exact external scheme and value.
60 ///
61 /// # Errors
62 ///
63 /// Returns a domain error when the lookup value is invalid or persisted
64 /// data cannot be decoded safely.
65 fn find_by_external_identifier(
66 &self,
67 scheme: &IdentifierScheme,
68 value: &str,
69 ) -> Result<Vec<ObjectRef>>;
70
71 /// Loads all metadata assertions attached to `target` in deterministic order.
72 ///
73 /// # Errors
74 ///
75 /// Returns a domain error when the target kind is unsupported or persisted
76 /// data cannot be decoded safely.
77 fn metadata(&self, target: ObjectRef) -> Result<Vec<MetadataAssertion>>;
78
79 /// Loads every ordered value for one property on `target`.
80 ///
81 /// # Errors
82 ///
83 /// Returns a domain error when the target kind is unsupported or persisted
84 /// data cannot be decoded safely.
85 fn metadata_values(
86 &self,
87 target: ObjectRef,
88 property: &MetadataProperty,
89 ) -> Result<Vec<MetadataValue>>;
90
91 /// Finds every object carrying `property`, preserving value repetition.
92 ///
93 /// # Errors
94 ///
95 /// Returns a domain error when persisted data cannot be decoded safely.
96 fn query_by_metadata_property(&self, property: &MetadataProperty)
97 -> Result<Vec<MetadataMatch>>;
98
99 /// Loads all production activities in deterministic identity order.
100 ///
101 /// # Errors
102 ///
103 /// Returns a storage-domain error when persisted activity data cannot be
104 /// read or decoded safely.
105 fn activities(&self) -> Result<Vec<Activity>>;
106
107 /// Loads activities that produce `representation_id`.
108 ///
109 /// # Errors
110 ///
111 /// Returns a domain error when the representation is absent or persisted
112 /// activity data cannot be read safely.
113 fn activities_producing(&self, representation_id: RepresentationId) -> Result<Vec<Activity>>;
114
115 /// Loads activities that consume `representation_id`.
116 ///
117 /// # Errors
118 ///
119 /// Returns a domain error when the representation is absent or persisted
120 /// activity data cannot be read safely.
121 fn activities_consuming(&self, representation_id: RepresentationId) -> Result<Vec<Activity>>;
122
123 /// Returns every transitive provenance ancestor of `representation_id`.
124 ///
125 /// # Errors
126 ///
127 /// Returns a domain error when the representation is absent or persisted
128 /// provenance cannot be traversed safely.
129 fn ancestors(&self, representation_id: RepresentationId) -> Result<Vec<RepresentationId>>;
130
131 /// Returns every transitive provenance descendant of `representation_id`.
132 ///
133 /// # Errors
134 ///
135 /// Returns a domain error when the representation is absent or persisted
136 /// provenance cannot be traversed safely.
137 fn descendants(&self, representation_id: RepresentationId) -> Result<Vec<RepresentationId>>;
138
139 /// Returns the newest durable revision, or `None` for an empty journal.
140 ///
141 /// # Errors
142 ///
143 /// Returns a storage-domain error when persisted revision data is invalid.
144 fn latest_revision(&self) -> Result<Option<Revision>>;
145
146 /// Returns revisions after `sequence` in ascending order, capped by `limit`.
147 ///
148 /// # Errors
149 ///
150 /// Returns a domain error when `limit` is zero or excessive, or when
151 /// persisted revision data is invalid.
152 fn changes_since(&self, sequence: u64, limit: u32) -> Result<Vec<Revision>>;
153
154 /// Loads the semantic events for one revision in stable position order.
155 ///
156 /// # Errors
157 ///
158 /// Returns a domain error when the revision is absent or persisted event
159 /// data is invalid.
160 fn events_for_revision(&self, revision_id: RevisionId) -> Result<Vec<RevisionEvent>>;
161}
162
163/// Transactional mutation operations required from a persistence backend.
164pub trait ProductionStoreTransaction {
165 /// Returns this transaction's stable identity.
166 fn id(&self) -> TransactionId;
167
168 /// Returns the current lifecycle state.
169 fn state(&self) -> TransactionState;
170
171 /// Sets the origin and message for the revision created on commit.
172 ///
173 /// # Errors
174 ///
175 /// Returns a domain error when the transaction is already closed.
176 fn set_revision_context(&mut self, context: RevisionContext) -> Result<()>;
177
178 /// Stages one prepared original-media aggregate atomically.
179 ///
180 /// # Errors
181 ///
182 /// Returns a domain error when the transaction is closed or persistence
183 /// rejects the aggregate.
184 fn import_original(&mut self, import: &OriginalMediaImport) -> Result<()>;
185
186 /// Stages a representation and its newly imported resources on an existing asset.
187 ///
188 /// # Errors
189 ///
190 /// Returns a domain error when the transaction is closed, the owning asset
191 /// does not exist, or persistence rejects the aggregate.
192 fn add_representation(&mut self, import: &RepresentationImport) -> Result<()>;
193
194 /// Stages an explicitly confirmed resource locator.
195 ///
196 /// # Errors
197 ///
198 /// Returns a domain error when the transaction is closed or persistence
199 /// rejects the locator.
200 fn add_locator(&mut self, locator: &Locator) -> Result<()>;
201
202 /// Stages retirement of one superseded resource locator.
203 ///
204 /// # Errors
205 ///
206 /// Returns a domain error when the transaction is closed, the locator does
207 /// not exist, or persistence fails.
208 fn retire_locator(&mut self, locator_id: crate::LocatorId) -> Result<()>;
209
210 /// Stages a configured resolver search root.
211 ///
212 /// # Errors
213 ///
214 /// Returns a domain error when the transaction is closed or persistence
215 /// rejects the root.
216 fn add_media_root(&mut self, root: MediaRoot) -> Result<()>;
217
218 /// Enables or disables a configured resolver search root.
219 ///
220 /// Setting the existing state is an idempotent no-op.
221 ///
222 /// # Errors
223 ///
224 /// Returns a domain error when the transaction is closed, the root does not
225 /// exist, or persistence fails.
226 fn set_media_root_enabled(&mut self, root_id: crate::MediaRootId, enabled: bool) -> Result<()>;
227
228 /// Stages removal of a configured resolver search root.
229 ///
230 /// # Errors
231 ///
232 /// Returns a domain error when the transaction is closed, the root does not
233 /// exist, or persistence fails.
234 fn remove_media_root(&mut self, root_id: crate::MediaRootId) -> Result<()>;
235
236 /// Stages an external identifier attachment.
237 ///
238 /// # Errors
239 ///
240 /// Returns a domain error when the transaction is closed, the target does
241 /// not exist, the attachment already exists, or persistence fails.
242 fn add_external_identifier(
243 &mut self,
244 target: ObjectRef,
245 identifier: &ExternalIdentifier,
246 ) -> Result<()>;
247
248 /// Stages removal of one exact external identifier attachment.
249 ///
250 /// # Errors
251 ///
252 /// Returns a domain error when the transaction is closed, the attachment
253 /// does not exist, the target kind is unsupported, or persistence fails.
254 fn remove_external_identifier(
255 &mut self,
256 target: ObjectRef,
257 identifier: &ExternalIdentifier,
258 ) -> Result<()>;
259
260 /// Appends one value to an object's metadata property.
261 ///
262 /// # Errors
263 ///
264 /// Returns a domain error when the transaction is closed, the target does
265 /// not exist or is unsupported, encoding fails, or persistence fails.
266 fn add_metadata_value(
267 &mut self,
268 target: ObjectRef,
269 property: &MetadataProperty,
270 value: &MetadataValue,
271 ) -> Result<()>;
272
273 /// Atomically replaces all values of one metadata property.
274 ///
275 /// An empty value slice removes the property.
276 ///
277 /// # Errors
278 ///
279 /// Returns a domain error when the transaction is closed, the target does
280 /// not exist or is unsupported, encoding fails, or persistence fails.
281 fn replace_metadata_values(
282 &mut self,
283 target: ObjectRef,
284 property: &MetadataProperty,
285 values: &[MetadataValue],
286 ) -> Result<()>;
287
288 /// Removes all values of one metadata property.
289 ///
290 /// # Errors
291 ///
292 /// Returns a domain error when the transaction is closed, the property is
293 /// absent, the target kind is unsupported, or persistence fails.
294 fn remove_metadata_property(
295 &mut self,
296 target: ObjectRef,
297 property: &MetadataProperty,
298 ) -> Result<()>;
299
300 /// Stages a complete production activity with its input and output edges.
301 ///
302 /// # Errors
303 ///
304 /// Returns a domain error when the transaction is closed, a referenced
305 /// representation is absent, the activity already exists, its edges would
306 /// create a provenance cycle, or persistence fails.
307 fn create_activity(&mut self, activity: &Activity) -> Result<()>;
308
309 /// Atomically makes every staged mutation durable.
310 ///
311 /// # Errors
312 ///
313 /// Returns a domain error when the transaction is closed or commit fails.
314 fn commit(&mut self) -> Result<()>;
315
316 /// Explicitly discards every staged mutation.
317 ///
318 /// # Errors
319 ///
320 /// Returns a domain error when the transaction is closed or rollback fails.
321 fn rollback(&mut self) -> Result<()>;
322}
323
324/// A production persistence backend with explicit domain transactions.
325pub trait ProductionStore: ProductionRead {
326 /// Backend-specific transaction implementation borrowing this store.
327 type Transaction<'production>: ProductionStoreTransaction
328 where
329 Self: 'production;
330
331 /// Begins a transaction for domain mutations.
332 ///
333 /// # Errors
334 ///
335 /// Returns a storage-domain error when a transaction cannot be started.
336 fn begin_transaction(&mut self) -> Result<Self::Transaction<'_>>;
337}