Skip to main content

dex_sdk/
flow_timeout_handler_options.rs

1// Copyright (c) 2026 Super Durable, Inc.
2//
3// Licensed under the Sustainable Use License 1.0.
4// You may not use this file except in compliance with the License.
5// See the LICENSE file in the repository root.
6//
7// SPDX-License-Identifier: LicenseRef-Sustainable-Use-1.0
8
9use std::time::Duration;
10
11use crate::attribute::{AttributeLock, AttributeMapLoad};
12use crate::channel::{ChannelLoad, ChannelMapLoad};
13use crate::step_options::ErasedStepOptions;
14use crate::{AttributeMap, Channel, ChannelMap, RetryPolicy, Step, StepDurability, StepOptions};
15
16/// Routes exhausted Flow timeout-handler retries to an input-free Step.
17#[derive(Clone)]
18pub struct FlowTimeoutHandlerFailure {
19    pub(crate) step_type: &'static str,
20    pub(crate) options: Option<ErasedStepOptions>,
21}
22
23impl FlowTimeoutHandlerFailure {
24    /// Routes failure to `step` using its registered options.
25    ///
26    /// The Step receives unit input and reads the terminal handler error from
27    /// [`Context::recovery_error`](crate::Context::recovery_error).
28    pub fn proceed_to<RecoveryStep>(step: &RecoveryStep) -> Self
29    where
30        RecoveryStep: Step<Input = ()>,
31    {
32        Self {
33            step_type: step.step_type(),
34            options: None,
35        }
36    }
37
38    /// Routes failure to `step` with movement-specific Step options.
39    pub fn proceed_to_with_options<RecoveryStep>(
40        step: &RecoveryStep,
41        options: StepOptions<()>,
42    ) -> Self
43    where
44        RecoveryStep: Step<Input = ()>,
45    {
46        Self {
47            step_type: step.step_type(),
48            options: Some(options.into()),
49        }
50    }
51}
52
53/// Configures execution and selective state loading for a Flow timeout handler.
54///
55/// Durations start when the soft Flow timeout fires. Omitted fields preserve the server's Execute
56/// defaults. AttributeMap contents and pending Channel messages are loaded only when selected.
57#[derive(Clone)]
58pub struct FlowTimeoutHandlerOptions {
59    pub(crate) method_timeout: Option<Duration>,
60    pub(crate) heartbeat_timeout: Option<Duration>,
61    pub(crate) retry: Option<RetryPolicy>,
62    pub(crate) failure: Option<FlowTimeoutHandlerFailure>,
63    pub(crate) durability: StepDurability,
64    pub(crate) locks: Vec<AttributeLock>,
65    pub(crate) load_attribute_maps: Vec<AttributeMapLoad>,
66    pub(crate) load_channels: Vec<ChannelLoad>,
67    pub(crate) load_channel_maps: Vec<ChannelMapLoad>,
68}
69
70impl FlowTimeoutHandlerOptions {
71    /// Creates timeout-handler options that preserve server defaults.
72    pub fn new() -> Self {
73        Self {
74            method_timeout: None,
75            heartbeat_timeout: None,
76            retry: None,
77            failure: None,
78            durability: StepDurability::Default,
79            locks: Vec::new(),
80            load_attribute_maps: Vec::new(),
81            load_channels: Vec::new(),
82            load_channel_maps: Vec::new(),
83        }
84    }
85
86    /// Sets the maximum duration of one timeout-handler attempt.
87    pub fn method_timeout(mut self, value: Duration) -> Self {
88        self.method_timeout = Some(value);
89        self
90    }
91
92    /// Sets the timeout for progress heartbeats from the timeout handler.
93    pub fn heartbeat_timeout(mut self, value: Duration) -> Self {
94        self.heartbeat_timeout = Some(value);
95        self
96    }
97
98    /// Sets retry behavior for the timeout handler's logical execution.
99    pub fn retry(mut self, value: RetryPolicy) -> Self {
100        self.retry = Some(value);
101        self
102    }
103
104    /// Sets routing after all timeout-handler attempts fail.
105    pub fn failure(mut self, value: FlowTimeoutHandlerFailure) -> Self {
106        self.failure = Some(value);
107        self
108    }
109
110    /// Overrides persistence durability for the timeout-handler response.
111    pub fn durability(mut self, value: StepDurability) -> Self {
112        self.durability = value;
113        self
114    }
115
116    /// Adds an Attribute lock held for each timeout-handler attempt.
117    pub fn lock(mut self, value: AttributeLock) -> Self {
118        self.locks.push(value);
119        self
120    }
121
122    /// Loads every current instance of `attribute_map` for the timeout handler.
123    pub fn load_attribute_map<T>(mut self, attribute_map: &AttributeMap<T>) -> Self {
124        self.load_attribute_maps.push(AttributeMapLoad {
125            name: attribute_map.name().to_owned(),
126            instance: None,
127        });
128        self
129    }
130
131    /// Loads one AttributeMap instance for the timeout handler.
132    pub fn load_attribute_map_instance(mut self, load: AttributeMapLoad) -> Self {
133        self.load_attribute_maps.push(load);
134        self
135    }
136
137    /// Loads one Channel's pending messages for the timeout handler.
138    pub fn load_channel<T>(mut self, channel: &Channel<T>) -> Self {
139        self.load_channels.push(ChannelLoad {
140            name: channel.name().to_owned(),
141        });
142        self
143    }
144
145    /// Loads every current ChannelMap instance's pending messages for the timeout handler.
146    pub fn load_channel_map<T>(mut self, channel_map: &ChannelMap<T>) -> Self {
147        self.load_channel_maps.push(ChannelMapLoad {
148            name: channel_map.name().to_owned(),
149            instance: None,
150        });
151        self
152    }
153
154    /// Loads one ChannelMap instance's pending messages for the timeout handler.
155    pub fn load_channel_map_instance(mut self, load: ChannelMapLoad) -> Self {
156        self.load_channel_maps.push(load);
157        self
158    }
159}
160
161impl Default for FlowTimeoutHandlerOptions {
162    fn default() -> Self {
163        Self::new()
164    }
165}