Expand description
Enhanced retry middleware for Tower services.
This crate provides advanced retry functionality beyond Tower’s built-in retry, with flexible backoff strategies, retry predicates, and comprehensive event system.
§Features
- IntervalFunction abstraction: Pluggable backoff strategies
- Fixed interval
- Exponential backoff with configurable multiplier
- Exponential random backoff with randomization factor
- Custom function-based backoff
- Per-request configuration: Extract max attempts from the request
- Retry predicates: Control which errors should be retried
- Event system: Observability through retry events
- Flexible configuration: Builder API with sensible defaults
§Examples
§Basic Retry with Exponential Backoff
use tower_resilience_retry::RetryLayer;
use tower::ServiceBuilder;
use std::time::Duration;
// Create retry layer with exponential backoff
let retry_layer = RetryLayer::<String, String, MyError>::builder()
.max_attempts(5)
.exponential_backoff(Duration::from_millis(100))
.on_retry(|attempt, delay| {
println!("Retry attempt {} after {:?}", attempt, delay);
})
.build();
// Apply to a service
let service = ServiceBuilder::new()
.layer(retry_layer)
.service(tower::service_fn(|req: String| async move {
Ok::<_, MyError>(format!("Response: {}", req))
}));§Per-Request Max Attempts
Extract retry configuration from the request itself:
use tower_resilience_retry::RetryLayer;
use tower::ServiceBuilder;
use std::time::Duration;
#[derive(Clone)]
struct MyRequest {
is_idempotent: bool,
data: String,
}
// Idempotent requests can retry more aggressively
let retry_layer = RetryLayer::<MyRequest, (), MyError>::builder()
.max_attempts_fn(|req: &MyRequest| {
if req.is_idempotent { 5 } else { 1 }
})
.exponential_backoff(Duration::from_millis(100))
.build();§Fallback After Retry Exhaustion
When retries are exhausted, you can provide a fallback response using standard error handling:
use tower_resilience_retry::RetryLayer;
use tower::{Service, ServiceBuilder, ServiceExt};
use std::time::Duration;
let retry_layer = RetryLayer::<String, String, MyError>::builder()
.max_attempts(3)
.exponential_backoff(Duration::from_millis(100))
.build();
let mut service = ServiceBuilder::new()
.layer(retry_layer)
.service(tower::service_fn(|req: String| async move {
Err::<String, MyError>(MyError) // Always fails
}));
// Handle retry exhaustion with fallback
let result = service.ready().await?.call("request".to_string()).await
.unwrap_or_else(|_| "Fallback: Service unavailable".to_string());§Fallback with Cached Data
use tower_resilience_retry::RetryLayer;
use tower::{Service, ServiceBuilder, ServiceExt};
use std::time::Duration;
use std::sync::Arc;
use std::collections::HashMap;
let cache = Arc::new(std::sync::RwLock::new(HashMap::new()));
cache.write().unwrap().insert("key", "cached value");
let retry_layer = RetryLayer::<String, String, MyError>::builder()
.max_attempts(3)
.exponential_backoff(Duration::from_millis(50))
.build();
let mut service = ServiceBuilder::new()
.layer(retry_layer)
.service(tower::service_fn(|req: String| async move {
Err::<String, MyError>(MyError)
}));
let cache_clone = Arc::clone(&cache);
let result = service.ready().await?.call("key".to_string()).await
.unwrap_or_else(|_| {
cache_clone.read().unwrap()
.get("key")
.map(|s| s.to_string())
.unwrap_or_else(|| "Default value".to_string())
});Structs§
- Aimd
Budget - AIMD (Additive Increase Multiplicative Decrease) retry budget.
- Exponential
Backoff - Exponential backoff with configurable multiplier.
- Exponential
Random Backoff - Exponential backoff with randomization to prevent thundering herd.
- Fixed
Interval - Fixed interval backoff - returns the same duration for every retry.
- FnInterval
- Function-based interval implementation.
- Retry
- A Tower
Servicethat retries failed requests. - Retry
Budget Builder - Builder for creating retry budgets.
- Retry
Config - Configuration for the retry middleware.
- Retry
Config Builder - Builder for
RetryConfig. - Retry
Layer - A Tower
Layerthat applies retry logic to a service. - Retry
Policy - Policy for retry behavior.
- Token
Bucket Budget - Token bucket retry budget.
Enums§
- MaxAttempts
Source - Source for determining the maximum number of retry attempts.
- Retry
Event - Events emitted by the retry middleware.
Traits§
- Interval
Function - Abstraction for computing retry intervals.
- Retry
Budget - A budget that controls how many retries are allowed.
Type Aliases§
- Response
Predicate - Determines whether a successful response should be retried.
- Retry
Predicate - Determines whether an error should be retried.