use crate::client::interceptors::context::Error;
use crate::client::interceptors::InterceptorContext;
use crate::client::orchestrator::{BoxError, OrchestratorError};
use crate::config_bag::ConfigBag;
use aws_smithy_types::retry::ErrorKind;
use std::fmt::Debug;
use std::time::Duration;
pub enum ShouldAttempt {
Yes,
No,
YesAfterDelay(Duration),
}
pub trait RetryStrategy: Send + Sync + Debug {
fn should_attempt_initial_request(&self, cfg: &ConfigBag) -> Result<ShouldAttempt, BoxError>;
fn should_attempt_retry(
&self,
context: &InterceptorContext,
cfg: &ConfigBag,
) -> Result<ShouldAttempt, BoxError>;
}
#[non_exhaustive]
#[derive(Eq, PartialEq, Debug)]
pub enum RetryReason {
Error(ErrorKind),
Explicit(Duration),
}
pub trait ClassifyRetry: Send + Sync + Debug {
fn classify_retry(&self, error: &OrchestratorError<Error>) -> Option<RetryReason>;
}
#[derive(Debug)]
pub struct RetryClassifiers {
inner: Vec<Box<dyn ClassifyRetry>>,
}
impl RetryClassifiers {
pub fn new() -> Self {
Self {
inner: Vec::with_capacity(1),
}
}
pub fn with_classifier(mut self, retry_classifier: impl ClassifyRetry + 'static) -> Self {
self.inner.push(Box::new(retry_classifier));
self
}
}
impl ClassifyRetry for RetryClassifiers {
fn classify_retry(&self, error: &OrchestratorError<Error>) -> Option<RetryReason> {
self.inner.iter().find_map(|cr| cr.classify_retry(error))
}
}