Skip to main content

qubit_http/request/
http_request_retry_override.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//! Request-level retry override options.
11
12use crate::HttpRetryMethodPolicy;
13
14/// Per-request overrides for the client retry strategy.
15///
16/// This type allows callers to:
17/// - force-enable retry even when client-level retry is disabled;
18/// - force-disable retry for one request;
19/// - override the retryable-method policy for one request;
20/// - optionally honor `Retry-After` on retryable status responses (`429` and
21///   `5xx`).
22#[derive(Debug, Clone, PartialEq, Eq, Default)]
23pub struct HttpRequestRetryOverride {
24    /// Force retry on for this request (unless explicitly force-disabled).
25    force_enable: bool,
26    /// Force retry off for this request.
27    force_disable: bool,
28    /// Optional method-policy override for this request.
29    method_policy: Option<HttpRetryMethodPolicy>,
30    /// Whether to honor `Retry-After` on retryable status responses.
31    honor_retry_after: bool,
32}
33
34impl HttpRequestRetryOverride {
35    /// Creates an empty override that follows client-level retry settings.
36    ///
37    /// # Returns
38    /// New [`HttpRequestRetryOverride`] with all per-request overrides disabled.
39    pub fn new() -> Self {
40        Self::default()
41    }
42
43    /// Enables force-retry for this request and clears force-disable.
44    ///
45    /// # Returns
46    /// Updated override for chaining.
47    pub fn force_enable(mut self) -> Self {
48        self.force_enable = true;
49        self.force_disable = false;
50        self
51    }
52
53    /// Enables force-disable for this request and clears force-enable.
54    ///
55    /// # Returns
56    /// Updated override for chaining.
57    pub fn force_disable(mut self) -> Self {
58        self.force_disable = true;
59        self.force_enable = false;
60        self
61    }
62
63    /// Sets the per-request retryable-method policy override.
64    ///
65    /// # Parameters
66    /// - `policy`: Method policy to use for this request.
67    ///
68    /// # Returns
69    /// Updated override for chaining.
70    pub fn with_method_policy(mut self, policy: HttpRetryMethodPolicy) -> Self {
71        self.method_policy = Some(policy);
72        self
73    }
74
75    /// Enables or disables honoring `Retry-After` for this request.
76    ///
77    /// # Parameters
78    /// - `enabled`: `true` to honor `Retry-After` on retryable status
79    ///   responses (`429` and `5xx`).
80    ///
81    /// # Returns
82    /// Updated override for chaining.
83    pub fn with_honor_retry_after(mut self, enabled: bool) -> Self {
84        self.honor_retry_after = enabled;
85        self
86    }
87
88    /// Returns whether force-enable is active for this request.
89    ///
90    /// # Returns
91    /// `true` when retry is force-enabled at request level.
92    pub fn is_force_enable(&self) -> bool {
93        self.force_enable
94    }
95
96    /// Returns whether force-disable is active for this request.
97    ///
98    /// # Returns
99    /// `true` when retry is force-disabled at request level.
100    pub fn is_force_disable(&self) -> bool {
101        self.force_disable
102    }
103
104    /// Returns the per-request method-policy override, if present.
105    ///
106    /// # Returns
107    /// Optional override for [`HttpRetryMethodPolicy`].
108    pub fn method_policy(&self) -> Option<HttpRetryMethodPolicy> {
109        self.method_policy
110    }
111
112    /// Returns whether `Retry-After` should be honored for this request.
113    ///
114    /// # Returns
115    /// `true` when this request should honor `Retry-After` on retryable status
116    /// responses (`429` and `5xx`).
117    pub fn should_honor_retry_after(&self) -> bool {
118        self.honor_retry_after
119    }
120
121    /// Resolves request-level force-enable/force-disable against client defaults.
122    ///
123    /// # Parameters
124    /// - `client_enabled`: Client-level retry enabled flag.
125    ///
126    /// # Returns
127    /// Effective retry-enabled flag for this request.
128    pub(crate) fn resolve_enabled(&self, client_enabled: bool) -> bool {
129        if self.force_disable {
130            false
131        } else if self.force_enable {
132            true
133        } else {
134            client_enabled
135        }
136    }
137
138    /// Resolves effective method policy from request-level override + client policy.
139    ///
140    /// # Parameters
141    /// - `client_policy`: Client-level method policy.
142    ///
143    /// # Returns
144    /// Effective method policy for this request.
145    pub(crate) fn resolve_method_policy(
146        &self,
147        client_policy: HttpRetryMethodPolicy,
148    ) -> HttpRetryMethodPolicy {
149        self.method_policy.unwrap_or(client_policy)
150    }
151}