1use std::time::Duration;
10
11use std::sync::Arc;
12
13use dex_protocol::dex::{AttributeSyncConfig, IndexConfig};
14
15use crate::registry::physical_name;
16use crate::step::{ErasedValue, TypedValue};
17use crate::{Attribute, AttributeMap, FlowConfig, FlowTimeoutHandlerOptions, RetryPolicy, Value};
18
19#[derive(Clone, Copy, Debug, Eq, PartialEq)]
20pub enum IdReusePolicy {
22 Default,
24 AllowIfPreviousFailed,
26 AllowIfNotRunning,
28 Disallow,
30 TerminateIfRunning,
32}
33
34#[derive(Clone, Copy, Debug, Eq, PartialEq)]
35pub enum FlowTimeoutPolicy {
37 Default,
39 Fail,
41 Cancel,
43 Handler,
45}
46
47#[derive(Clone)]
48pub struct StartFlowOptions {
67 pub(crate) timeout: Option<Duration>,
68 pub(crate) timeout_policy: FlowTimeoutPolicy,
69 pub(crate) timeout_handler_options: Option<FlowTimeoutHandlerOptions>,
70 pub(crate) start_delay: Option<Duration>,
71 pub(crate) id_reuse_policy: IdReusePolicy,
72 pub(crate) retry_policy: Option<RetryPolicy>,
73 pub(crate) config_override: Option<FlowConfig>,
74 pub(crate) ignore_already_started: bool,
75 pub(crate) request_id: Option<String>,
76 pub(crate) attributes: Vec<InitialAttribute>,
77}
78
79#[derive(Clone)]
80pub(crate) struct InitialAttribute {
81 pub(crate) key: String,
82 pub(crate) value: Arc<dyn ErasedValue>,
83 pub(crate) index_config: Option<IndexConfig>,
84 pub(crate) sync_config: Option<AttributeSyncConfig>,
85}
86
87impl InitialAttribute {
88 pub(crate) fn for_attribute<T: Value>(attribute: &Attribute<T>, value: T) -> Self {
89 Self {
90 key: attribute.name().to_string(),
91 value: Arc::new(TypedValue(value)),
92 index_config: attribute.index().map(|index| index.proto_config(false)),
93 sync_config: attribute.sync_config(),
94 }
95 }
96
97 pub(crate) fn for_attribute_map<T: Value>(
98 attribute: &AttributeMap<T>,
99 instance: &str,
100 value: T,
101 ) -> Self {
102 Self {
103 key: physical_name(attribute.name(), instance),
104 value: Arc::new(TypedValue(value)),
105 index_config: attribute.index().map(|index| index.proto_config(true)),
106 sync_config: attribute.sync_config(),
107 }
108 }
109}
110
111impl StartFlowOptions {
112 pub fn new() -> Self {
114 Self {
115 timeout: None,
116 timeout_policy: FlowTimeoutPolicy::Default,
117 timeout_handler_options: None,
118 start_delay: None,
119 id_reuse_policy: IdReusePolicy::Default,
120 retry_policy: None,
121 config_override: None,
122 ignore_already_started: false,
123 request_id: None,
124 attributes: Vec::new(),
125 }
126 }
127
128 pub fn timeout(mut self, value: Duration) -> Self {
130 self.timeout = Some(value);
131 self
132 }
133
134 pub fn timeout_policy(mut self, value: FlowTimeoutPolicy) -> Self {
138 self.timeout_policy = value;
139 self
140 }
141
142 pub fn timeout_handler_options(mut self, value: FlowTimeoutHandlerOptions) -> Self {
147 self.timeout_handler_options = Some(value);
148 self
149 }
150
151 pub fn start_delay(mut self, value: Duration) -> Self {
153 self.start_delay = Some(value);
154 self
155 }
156
157 pub fn id_reuse_policy(mut self, value: IdReusePolicy) -> Self {
159 self.id_reuse_policy = value;
160 self
161 }
162
163 pub fn retry_policy(mut self, value: RetryPolicy) -> Self {
165 self.retry_policy = Some(value);
166 self
167 }
168
169 pub fn initial_attribute<T: Value>(mut self, attribute: &Attribute<T>, value: T) -> Self {
171 self.attributes
172 .push(InitialAttribute::for_attribute(attribute, value));
173 self
174 }
175
176 pub fn initial_attribute_map<T: Value>(
179 mut self,
180 attribute: &AttributeMap<T>,
181 instance: &str,
182 value: T,
183 ) -> Self {
184 self.attributes.push(InitialAttribute::for_attribute_map(
185 attribute, instance, value,
186 ));
187 self
188 }
189
190 pub fn config_override(mut self, value: FlowConfig) -> Self {
192 self.config_override = Some(value);
193 self
194 }
195
196 pub fn ignore_already_started(mut self, value: bool) -> Self {
198 self.ignore_already_started = value;
199 self
200 }
201
202 pub fn request_id(mut self, value: impl Into<String>) -> Self {
204 self.request_id = Some(value.into());
205 self
206 }
207}
208
209impl Default for StartFlowOptions {
210 fn default() -> Self {
211 Self::new()
212 }
213}
214
215#[cfg(test)]
216mod tests {
217 use super::StartFlowOptions;
218 use crate::{Attribute, AttributeMap};
219
220 #[test]
221 fn initial_attributes_retain_sync_configuration() {
222 let plain = Attribute::<String>::new("plain");
223 let synced = Attribute::<String>::new("synced").sync_to_attribute_store();
224 let synced_map = AttributeMap::<String>::new("map").sync_to_attribute_store();
225 let options = StartFlowOptions::new()
226 .initial_attribute(&plain, "plain".to_string())
227 .initial_attribute(&synced, "synced".to_string())
228 .initial_attribute_map(&synced_map, "tenant-1", "mapped".to_string());
229
230 assert!(options.attributes[0].sync_config.is_none());
231 assert_eq!(
232 options.attributes[1]
233 .sync_config
234 .as_ref()
235 .map(|config| config.enabled),
236 Some(true)
237 );
238 assert_eq!(
239 options.attributes[2]
240 .sync_config
241 .as_ref()
242 .map(|config| config.enabled),
243 Some(true)
244 );
245 }
246}