Skip to main content

qubit_retry/options/
attempt_timeout_policy.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! Attempt timeout policy.
11//!
12
13use std::fmt;
14use std::str::FromStr;
15
16use serde::{
17    Deserialize,
18    Serialize,
19};
20
21/// Action taken when one attempt exceeds its configured per-attempt timeout.
22///
23/// The policy is used as the default decision for configured attempt-timeout
24/// failures. Elapsed-budget effective timeouts stop the retry flow with
25/// [`crate::RetryErrorReason::MaxOperationElapsedExceeded`] or
26/// [`crate::RetryErrorReason::MaxTotalElapsedExceeded`] instead. Explicit
27/// failure listeners can still return their own decision for configured
28/// timeouts.
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
30pub enum AttemptTimeoutPolicy {
31    /// Retry timed-out attempts while normal retry limits allow it.
32    Retry,
33    /// Abort the retry flow immediately when an attempt times out.
34    Abort,
35}
36
37impl Default for AttemptTimeoutPolicy {
38    /// Creates the default attempt-timeout policy.
39    ///
40    /// # Returns
41    /// [`AttemptTimeoutPolicy::Retry`].
42    #[inline]
43    fn default() -> Self {
44        Self::Retry
45    }
46}
47
48impl fmt::Display for AttemptTimeoutPolicy {
49    /// Formats the policy as lower-case config text.
50    ///
51    /// # Parameters
52    /// - `f`: Formatter provided by the standard formatting machinery.
53    ///
54    /// # Returns
55    /// Formatter result.
56    ///
57    /// # Errors
58    /// Returns a formatting error only if the formatter rejects output.
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        match self {
61            Self::Retry => f.write_str("retry"),
62            Self::Abort => f.write_str("abort"),
63        }
64    }
65}
66
67impl FromStr for AttemptTimeoutPolicy {
68    /// Error returned when policy text is unsupported.
69    type Err = String;
70
71    /// Parses a timeout policy from config text.
72    ///
73    /// # Parameters
74    /// - `s`: Policy text. ASCII case is ignored.
75    ///
76    /// # Returns
77    /// Parsed [`AttemptTimeoutPolicy`].
78    ///
79    /// # Errors
80    /// Returns an error message when `s` is not `retry` or `abort`.
81    fn from_str(s: &str) -> Result<Self, Self::Err> {
82        match s.trim().to_ascii_lowercase().as_str() {
83            "retry" => Ok(Self::Retry),
84            "abort" => Ok(Self::Abort),
85            _ => Err("attempt timeout policy must be `retry` or `abort`".to_string()),
86        }
87    }
88}