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