@@ -23,7 +23,8 @@ use std::time::Duration;
2323/// let retry_policy = ExponentialBackoffRetryPolicy::new(Duration::from_millis(100))
2424/// .with_max_attempts(5)
2525/// .with_max_total_delay(Duration::from_secs(2))
26- /// .with_max_jitter(Duration::from_millis(30));
26+ /// .with_max_jitter(Duration::from_millis(30))
27+ /// .skip_retry_on_error(|e| matches!(e, VssError::InvalidRequestError(..)));
2728///
2829/// let result = retry(operation, &retry_policy);
2930///```
@@ -79,6 +80,14 @@ pub trait RetryPolicy: Sized {
7980 fn with_max_jitter ( self , max_jitter : Duration ) -> JitteredRetryPolicy < Self > {
8081 JitteredRetryPolicy { inner_policy : self , max_jitter }
8182 }
83+
84+ /// Skips retrying on errors that evaluate to `true` after applying `function`.
85+ fn skip_retry_on_error < F > ( self , function : F ) -> FilteredRetryPolicy < Self , F >
86+ where
87+ F : ' static + Fn ( & Self :: E ) -> bool ,
88+ {
89+ FilteredRetryPolicy { inner_policy : self , function }
90+ }
8291}
8392
8493/// Represents the context of a retry operation.
@@ -187,3 +196,25 @@ impl<T: RetryPolicy> RetryPolicy for JitteredRetryPolicy<T> {
187196 }
188197 }
189198}
199+
200+ /// Decorates the given `RetryPolicy` by not retrying on errors that match the given function.
201+ pub struct FilteredRetryPolicy < T : RetryPolicy , F > {
202+ inner_policy : T ,
203+ function : F ,
204+ }
205+
206+ impl < T , F , E > RetryPolicy for FilteredRetryPolicy < T , F >
207+ where
208+ T : RetryPolicy < E = E > ,
209+ F : Fn ( & E ) -> bool ,
210+ E : Error ,
211+ {
212+ type E = T :: E ;
213+ fn next_delay ( & self , context : & RetryContext < E > ) -> Option < Duration > {
214+ if ( self . function ) ( & context. error ) {
215+ None
216+ } else {
217+ self . inner_policy . next_delay ( context)
218+ }
219+ }
220+ }
0 commit comments