qiniu_http_client/client/retrier/
mod.rs

1mod error;
2mod limited;
3mod never;
4
5use super::{Idempotent, ResponseError, RetriedStatsInfo};
6use auto_impl::auto_impl;
7use dyn_clonable::clonable;
8use qiniu_http::RequestParts as HttpRequestParts;
9use std::{
10    fmt::{self, Debug},
11    ops::{Deref, DerefMut},
12};
13
14/// 请求重试器
15///
16/// 根据 HTTP 客户端返回的错误,决定是否重试请求,重试决定由 [`RetryDecision`] 定义。
17#[clonable]
18#[auto_impl(&, &mut, Box, Rc, Arc)]
19pub trait RequestRetrier: Clone + Debug + Sync + Send {
20    /// 作出重试决定
21    fn retry(&self, request: &mut HttpRequestParts, opts: RequestRetrierOptions<'_>) -> RetryResult;
22}
23
24/// 重试决定
25#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
26#[non_exhaustive]
27pub enum RetryDecision {
28    /// 不再重试
29    #[default]
30    DontRetry,
31
32    /// 切换到下一个服务器
33    TryNextServer,
34
35    /// 切换到备选终端地址
36    TryAlternativeEndpoints,
37
38    /// 重试当前请求
39    RetryRequest,
40
41    /// 节流
42    Throttled,
43}
44
45/// 重试器选项
46#[derive(Copy, Debug, Clone)]
47pub struct RequestRetrierOptions<'a> {
48    idempotent: Idempotent,
49    response_error: &'a ResponseError,
50    retried: &'a RetriedStatsInfo,
51}
52
53impl<'a> RequestRetrierOptions<'a> {
54    /// 创建重试器选项构建器
55    #[inline]
56    pub fn builder(
57        response_error: &'a ResponseError,
58        retried: &'a RetriedStatsInfo,
59    ) -> RequestRetrierOptionsBuilder<'a> {
60        RequestRetrierOptionsBuilder::new(response_error, retried)
61    }
62
63    /// 是否是幂等请求
64    #[inline]
65    pub fn idempotent(&self) -> Idempotent {
66        self.idempotent
67    }
68
69    /// 获取响应错误
70    #[inline]
71    pub fn response_error(&self) -> &ResponseError {
72        self.response_error
73    }
74
75    /// 获取重试统计信息
76    #[inline]
77    pub fn retried(&self) -> &RetriedStatsInfo {
78        self.retried
79    }
80}
81
82/// 重试器选项构建器
83#[derive(Copy, Debug, Clone)]
84pub struct RequestRetrierOptionsBuilder<'a>(RequestRetrierOptions<'a>);
85
86impl<'a> RequestRetrierOptionsBuilder<'a> {
87    /// 创建重试器选项构建器
88    #[inline]
89    pub fn new(response_error: &'a ResponseError, retried: &'a RetriedStatsInfo) -> Self {
90        Self(RequestRetrierOptions {
91            response_error,
92            retried,
93            idempotent: Default::default(),
94        })
95    }
96
97    /// 设置幂等请求
98    #[inline]
99    pub fn idempotent(&mut self, idempotent: Idempotent) -> &mut Self {
100        self.0.idempotent = idempotent;
101        self
102    }
103
104    /// 构建重试器选项
105    #[inline]
106    pub fn build(&self) -> RequestRetrierOptions<'a> {
107        self.0
108    }
109}
110
111/// 重试器结果
112#[derive(Clone)]
113pub struct RetryResult(RetryDecision);
114
115impl RetryResult {
116    /// 获取重试决定
117    #[inline]
118    pub fn decision(&self) -> RetryDecision {
119        self.0
120    }
121
122    /// 获取重试决定的可变引用
123    #[inline]
124    pub fn decision_mut(&mut self) -> &mut RetryDecision {
125        &mut self.0
126    }
127}
128
129impl From<RetryDecision> for RetryResult {
130    #[inline]
131    fn from(decision: RetryDecision) -> Self {
132        Self(decision)
133    }
134}
135
136impl From<RetryResult> for RetryDecision {
137    #[inline]
138    fn from(result: RetryResult) -> Self {
139        result.0
140    }
141}
142
143impl AsRef<RetryDecision> for RetryResult {
144    #[inline]
145    fn as_ref(&self) -> &RetryDecision {
146        &self.0
147    }
148}
149
150impl AsMut<RetryDecision> for RetryResult {
151    #[inline]
152    fn as_mut(&mut self) -> &mut RetryDecision {
153        &mut self.0
154    }
155}
156
157impl Deref for RetryResult {
158    type Target = RetryDecision;
159
160    #[inline]
161    fn deref(&self) -> &Self::Target {
162        &self.0
163    }
164}
165
166impl DerefMut for RetryResult {
167    #[inline]
168    fn deref_mut(&mut self) -> &mut Self::Target {
169        &mut self.0
170    }
171}
172
173impl Debug for RetryResult {
174    #[inline]
175    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176        self.0.fmt(f)
177    }
178}
179
180pub use error::ErrorRetrier;
181pub use limited::LimitedRetrier;
182pub use never::NeverRetrier;