mod error;
mod limited;
mod never;
use super::{Idempotent, ResponseError, RetriedStatsInfo};
use auto_impl::auto_impl;
use dyn_clonable::clonable;
use qiniu_http::RequestParts as HttpRequestParts;
use smart_default::SmartDefault;
use std::{
fmt::{self, Debug},
ops::{Deref, DerefMut},
};
#[clonable]
#[auto_impl(&, &mut, Box, Rc, Arc)]
pub trait RequestRetrier: Clone + Debug + Sync + Send {
fn retry(&self, request: &mut HttpRequestParts, opts: RequestRetrierOptions<'_>) -> RetryResult;
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, SmartDefault)]
#[non_exhaustive]
pub enum RetryDecision {
#[default]
DontRetry,
TryNextServer,
TryAlternativeEndpoints,
RetryRequest,
Throttled,
}
#[derive(Copy, Debug, Clone)]
pub struct RequestRetrierOptions<'a> {
idempotent: Idempotent,
response_error: &'a ResponseError,
retried: &'a RetriedStatsInfo,
}
impl<'a> RequestRetrierOptions<'a> {
#[inline]
pub fn builder(
response_error: &'a ResponseError,
retried: &'a RetriedStatsInfo,
) -> RequestRetrierOptionsBuilder<'a> {
RequestRetrierOptionsBuilder::new(response_error, retried)
}
#[inline]
pub fn idempotent(&self) -> Idempotent {
self.idempotent
}
#[inline]
pub fn response_error(&self) -> &ResponseError {
self.response_error
}
#[inline]
pub fn retried(&self) -> &RetriedStatsInfo {
self.retried
}
}
#[derive(Copy, Debug, Clone)]
pub struct RequestRetrierOptionsBuilder<'a>(RequestRetrierOptions<'a>);
impl<'a> RequestRetrierOptionsBuilder<'a> {
#[inline]
pub fn new(response_error: &'a ResponseError, retried: &'a RetriedStatsInfo) -> Self {
Self(RequestRetrierOptions {
response_error,
retried,
idempotent: Default::default(),
})
}
#[inline]
pub fn idempotent(&mut self, idempotent: Idempotent) -> &mut Self {
self.0.idempotent = idempotent;
self
}
#[inline]
pub fn build(&self) -> RequestRetrierOptions<'a> {
self.0
}
}
#[derive(Clone)]
pub struct RetryResult(RetryDecision);
impl RetryResult {
#[inline]
pub fn decision(&self) -> RetryDecision {
self.0
}
#[inline]
pub fn decision_mut(&mut self) -> &mut RetryDecision {
&mut self.0
}
}
impl From<RetryDecision> for RetryResult {
#[inline]
fn from(decision: RetryDecision) -> Self {
Self(decision)
}
}
impl From<RetryResult> for RetryDecision {
#[inline]
fn from(result: RetryResult) -> Self {
result.0
}
}
impl AsRef<RetryDecision> for RetryResult {
#[inline]
fn as_ref(&self) -> &RetryDecision {
&self.0
}
}
impl AsMut<RetryDecision> for RetryResult {
#[inline]
fn as_mut(&mut self) -> &mut RetryDecision {
&mut self.0
}
}
impl Deref for RetryResult {
type Target = RetryDecision;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for RetryResult {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Debug for RetryResult {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
pub use error::ErrorRetrier;
pub use limited::LimitedRetrier;
pub use never::NeverRetrier;