use super::RetryBody;
use crate::Request;
use rama_core::Context;
pub trait Policy<S, R, E>: Send + Sync + 'static {
fn retry(
&self,
ctx: Context<S>,
req: Request<RetryBody>,
result: Result<R, E>,
) -> impl Future<Output = PolicyResult<S, R, E>> + Send + '_;
fn clone_input(
&self,
ctx: &Context<S>,
req: &Request<RetryBody>,
) -> Option<(Context<S>, Request<RetryBody>)>;
}
impl<P, S, R, E> Policy<S, R, E> for &'static P
where
P: Policy<S, R, E>,
{
fn retry(
&self,
ctx: Context<S>,
req: Request<RetryBody>,
result: Result<R, E>,
) -> impl Future<Output = PolicyResult<S, R, E>> + Send + '_ {
(**self).retry(ctx, req, result)
}
fn clone_input(
&self,
ctx: &Context<S>,
req: &Request<RetryBody>,
) -> Option<(Context<S>, Request<RetryBody>)> {
(**self).clone_input(ctx, req)
}
}
impl<P, S, R, E> Policy<S, R, E> for std::sync::Arc<P>
where
P: Policy<S, R, E>,
{
fn retry(
&self,
ctx: Context<S>,
req: Request<RetryBody>,
result: Result<R, E>,
) -> impl Future<Output = PolicyResult<S, R, E>> + Send + '_ {
(**self).retry(ctx, req, result)
}
fn clone_input(
&self,
ctx: &Context<S>,
req: &Request<RetryBody>,
) -> Option<(Context<S>, Request<RetryBody>)> {
(**self).clone_input(ctx, req)
}
}
pub enum PolicyResult<S, R, E> {
Abort(Result<R, E>),
Retry {
ctx: Context<S>,
req: Request<RetryBody>,
},
}
impl<S, R, E> std::fmt::Debug for PolicyResult<S, R, E>
where
S: std::fmt::Debug,
R: std::fmt::Debug,
E: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PolicyResult::Abort(err) => write!(f, "PolicyResult::Abort({:?})", err),
PolicyResult::Retry { ctx, req } => write!(
f,
"PolicyResult::Retry {{ ctx: {:?}, req: {:?} }}",
ctx, req
),
}
}
}
macro_rules! impl_retry_policy_either {
($id:ident, $($param:ident),+ $(,)?) => {
impl<$($param),+, State, Response, Error> Policy<State, Response, Error> for rama_core::combinators::$id<$($param),+>
where
$($param: Policy<State, Response, Error>),+,
State: Clone + Send + Sync + 'static,
Response: Send + 'static,
Error: Send + 'static,
{
async fn retry(
&self,
ctx: Context<State>,
req: rama_http_types::Request<RetryBody>,
result: Result<Response, Error>,
) -> PolicyResult<State, Response, Error> {
match self {
$(
rama_core::combinators::$id::$param(policy) => policy.retry(ctx, req, result).await,
)+
}
}
fn clone_input(
&self,
ctx: &Context<State>,
req: &rama_http_types::Request<RetryBody>,
) -> Option<(Context<State>, rama_http_types::Request<RetryBody>)> {
match self {
$(
rama_core::combinators::$id::$param(policy) => policy.clone_input(ctx, req),
)+
}
}
}
};
}
rama_core::combinators::impl_either!(impl_retry_policy_either);