serdes_ai_retries/lib.rs
1//! # serdes-ai-retries
2//!
3//! Retry strategies and error handling for serdes-ai.
4//!
5//! This crate provides flexible retry mechanisms for handling transient
6//! failures in LLM API calls.
7//!
8//! ## Core Concepts
9//!
10//! - **[`RetryConfig`]**: Configure retry behavior
11//! - **[`WaitStrategy`]**: Define how long to wait between retries
12//! - **[`RetryCondition`]**: Determine which errors are retryable
13//! - **[`with_retry`]**: Execute operations with automatic retries
14//! - **[`RetryClient`]**: HTTP client with built-in retry support
15//!
16//! ## Wait Strategies
17//!
18//! - [`WaitStrategy::Fixed`]: Constant delay between attempts
19//! - [`WaitStrategy::ExponentialBackoff`]: Exponential delay with cap
20//! - [`WaitStrategy::ExponentialJitter`]: Exponential with randomization
21//! - [`WaitStrategy::Linear`]: Linearly increasing delay
22//! - [`WaitStrategy::RetryAfter`]: Respect server's Retry-After header
23//!
24//! ## Example
25//!
26//! ```ignore
27//! use serdes_ai_retries::{with_retry, RetryConfig, RetryableError};
28//! use std::time::Duration;
29//!
30//! let config = RetryConfig::new()
31//! .max_retries(3)
32//! .exponential_jitter(
33//! Duration::from_millis(100),
34//! Duration::from_secs(10),
35//! 0.1,
36//! );
37//!
38//! let result = with_retry(&config, || async {
39//! // Your async operation
40//! Ok::<_, RetryableError>("success")
41//! }).await?;
42//! ```
43//!
44//! ## HTTP Client with Retries
45//!
46//! ```ignore
47//! use serdes_ai_retries::RetryClient;
48//!
49//! let client = RetryClient::for_api();
50//!
51//! let response = client.get("https://api.example.com/data").await?;
52//! ```
53
54#![warn(missing_docs)]
55#![deny(unsafe_code)]
56
57pub mod backoff;
58pub mod config;
59pub mod error;
60pub mod executor;
61pub mod strategy;
62pub mod transport;
63
64// Re-exports
65pub use backoff::{ExponentialBackoff, ExponentialBackoffBuilder, FixedDelay, LinearBackoff};
66pub use config::{RetryCondition, RetryConfig, WaitStrategy};
67pub use error::{RetryResult, RetryableError};
68pub use executor::{with_retry, with_retry_state, AttemptInfo, Retry, RetryState};
69pub use strategy::{NoRetry, RetryStrategy};
70pub use transport::{RetryClient, RetryClientBuilder};
71
72/// Prelude for common imports.
73pub mod prelude {
74 pub use crate::{
75 with_retry, ExponentialBackoff, Retry, RetryClient, RetryConfig, RetryResult,
76 RetryStrategy, RetryableError, WaitStrategy,
77 };
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83 use std::time::Duration;
84
85 #[test]
86 fn test_prelude_imports() {
87 use crate::prelude::*;
88
89 let config = RetryConfig::new().max_retries(5);
90 assert_eq!(config.max_retries, 5);
91 }
92
93 #[test]
94 fn test_config_defaults() {
95 let config = RetryConfig::default();
96 assert_eq!(config.max_retries, 3);
97 }
98
99 #[test]
100 fn test_exponential_backoff() {
101 let backoff = ExponentialBackoff::new();
102 assert_eq!(backoff.max_retries, 3);
103 }
104
105 #[test]
106 fn test_fixed_delay() {
107 let delay = FixedDelay::new(Duration::from_secs(1), 5);
108 assert_eq!(delay.max_retries, 5);
109 }
110}