solti_model/resource/
preconditions.rs1use crate::{ModelError, ModelResult, Task, Uid};
6
7#[derive(Clone, Debug, Default, PartialEq, Eq)]
11pub struct WritePreconditions {
12 uid: Option<Uid>,
13 resource_version: Option<String>,
14}
15
16impl WritePreconditions {
17 #[inline]
19 pub const fn new() -> Self {
20 Self {
21 uid: None,
22 resource_version: None,
23 }
24 }
25
26 pub fn from_task(task: &Task) -> ModelResult<Self> {
32 Self::new()
33 .with_uid(task.uid().clone())
34 .with_resource_version(task.metadata().resource_version())
35 }
36
37 #[inline]
39 pub fn with_uid(mut self, uid: Uid) -> Self {
40 self.uid = Some(uid);
41 self
42 }
43
44 pub fn with_resource_version(
50 mut self,
51 resource_version: impl Into<String>,
52 ) -> ModelResult<Self> {
53 let resource_version = resource_version.into();
54 if resource_version.trim().is_empty() {
55 return Err(ModelError::Invalid(
56 "resourceVersion precondition must not be empty".into(),
57 ));
58 }
59 self.resource_version = Some(resource_version);
60 Ok(self)
61 }
62
63 #[inline]
65 pub fn uid(&self) -> Option<&Uid> {
66 self.uid.as_ref()
67 }
68
69 #[inline]
71 pub fn resource_version(&self) -> Option<&str> {
72 self.resource_version.as_deref()
73 }
74
75 #[inline]
77 pub fn is_empty(&self) -> bool {
78 self.uid.is_none() && self.resource_version.is_none()
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn empty_is_unconditional() {
88 assert!(WritePreconditions::new().is_empty());
89 }
90
91 #[test]
92 fn values_are_retained() {
93 let uid = Uid::new("resource-uid").unwrap();
94 let preconditions = WritePreconditions::new()
95 .with_uid(uid.clone())
96 .with_resource_version("42")
97 .unwrap();
98
99 assert_eq!(preconditions.uid(), Some(&uid));
100 assert_eq!(preconditions.resource_version(), Some("42"));
101 assert!(!preconditions.is_empty());
102 }
103
104 #[test]
105 fn empty_resource_version_is_rejected() {
106 let error = WritePreconditions::new()
107 .with_resource_version(" ")
108 .unwrap_err();
109 assert_eq!(
110 error.to_string(),
111 "invalid model: resourceVersion precondition must not be empty"
112 );
113 }
114
115 #[test]
116 fn unstored_task_cannot_be_captured() {
117 let task = Task::from_manifest(
118 crate::TaskManifest::new(
119 "unstored",
120 crate::TaskSpec::builder(
121 "slot",
122 crate::TaskWorkload::Embedded(crate::EmbeddedSpec::new("test").unwrap()),
123 1_000_u64,
124 )
125 .build()
126 .unwrap(),
127 )
128 .unwrap(),
129 )
130 .unwrap();
131
132 assert!(WritePreconditions::from_task(&task).is_err());
133 }
134}