Skip to main content

ironflow_engine/config/
delay.rs

1//! Configuration for delay (timed pause) steps.
2//!
3//! A [`DelayConfig`] pauses a workflow run for a specified duration.
4//! The worker releases its slot while the run sleeps and resumes
5//! it automatically when the delay elapses.
6
7use std::time::Duration;
8
9use serde::{Deserialize, Serialize};
10
11/// Configuration for a delay step.
12///
13/// The delay is stored as whole seconds for serialization simplicity.
14/// Sub-second precision is not needed for workflow pauses (cooldowns,
15/// rate limiting, scheduled retries).
16///
17/// # Examples
18///
19/// ```
20/// use ironflow_engine::config::delay::DelayConfig;
21///
22/// let config = DelayConfig::from_secs(300);
23/// assert_eq!(config.duration(), std::time::Duration::from_secs(300));
24///
25/// let zero = DelayConfig::from_secs(0);
26/// assert!(zero.is_zero());
27/// ```
28///
29/// # Panics
30///
31/// [`DelayConfig::from_secs`] does not panic. Invalid durations
32/// (negative or overflow) cannot be constructed because the inner
33/// value is `u64`.
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct DelayConfig {
36    /// Delay duration in seconds.
37    duration_secs: u64,
38}
39
40impl DelayConfig {
41    /// Create a delay configuration with the given number of seconds.
42    ///
43    /// # Examples
44    ///
45    /// ```
46    /// use ironflow_engine::config::delay::DelayConfig;
47    ///
48    /// let config = DelayConfig::from_secs(60);
49    /// assert_eq!(config.duration_secs(), 60);
50    /// ```
51    pub fn from_secs(secs: u64) -> Self {
52        Self {
53            duration_secs: secs,
54        }
55    }
56
57    /// The delay duration as a [`Duration`].
58    ///
59    /// # Examples
60    ///
61    /// ```
62    /// use ironflow_engine::config::delay::DelayConfig;
63    /// use std::time::Duration;
64    ///
65    /// assert_eq!(DelayConfig::from_secs(10).duration(), Duration::from_secs(10));
66    /// ```
67    pub fn duration(&self) -> Duration {
68        Duration::from_secs(self.duration_secs)
69    }
70
71    /// The raw seconds value.
72    pub fn duration_secs(&self) -> u64 {
73        self.duration_secs
74    }
75
76    /// Whether the delay is zero (immediate completion, no sleeping).
77    ///
78    /// # Examples
79    ///
80    /// ```
81    /// use ironflow_engine::config::delay::DelayConfig;
82    ///
83    /// assert!(DelayConfig::from_secs(0).is_zero());
84    /// assert!(!DelayConfig::from_secs(1).is_zero());
85    /// ```
86    pub fn is_zero(&self) -> bool {
87        self.duration_secs == 0
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn delay_config_from_secs() {
97        let config = DelayConfig::from_secs(300);
98        assert_eq!(config.duration_secs(), 300);
99        assert_eq!(config.duration(), Duration::from_secs(300));
100        assert!(!config.is_zero());
101    }
102
103    #[test]
104    fn delay_config_zero() {
105        let config = DelayConfig::from_secs(0);
106        assert!(config.is_zero());
107        assert_eq!(config.duration(), Duration::ZERO);
108    }
109
110    #[test]
111    fn delay_config_serde_roundtrip() {
112        let config = DelayConfig::from_secs(60);
113        let json = serde_json::to_string(&config).expect("serialize");
114        let back: DelayConfig = serde_json::from_str(&json).expect("deserialize");
115        assert_eq!(config.duration_secs(), back.duration_secs());
116    }
117}