use openai_ergonomic::{Client, Config, Response, Result};
use reqwest_middleware::ClientBuilder;
use reqwest_retry::{policies::ExponentialBackoff, RetryTransientMiddleware};
#[tokio::main]
async fn main() -> Result<()> {
println!("=== HTTP Middleware with Retry Example ===\n");
println!("1. Creating client with retry middleware");
let retry_policy = ExponentialBackoff::builder().build_with_max_retries(3);
let http_client = ClientBuilder::new(reqwest::Client::new())
.with(RetryTransientMiddleware::new_with_policy(retry_policy))
.build();
let config = Config::builder()
.api_key(
std::env::var("OPENAI_API_KEY")
.expect("OPENAI_API_KEY environment variable must be set"),
)
.http_client(http_client)
.build();
let client = Client::builder(config)?.build();
println!("Sending chat completion request (retries are automatic)...");
let builder = client.chat_simple("Hello! How are you today?");
match client.send_chat(builder).await {
Ok(response) => {
println!("\nSuccess! Response received:");
if let Some(content) = response.content() {
println!("{content}");
}
}
Err(e) => {
eprintln!("\nError after retries: {e}");
}
}
println!("\n2. Creating client with custom retry policy");
let custom_retry_policy = ExponentialBackoff::builder()
.retry_bounds(
std::time::Duration::from_millis(100), std::time::Duration::from_secs(30), )
.build_with_max_retries(5);
let custom_http_client = ClientBuilder::new(
reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(60))
.build()
.expect("Failed to build reqwest client"),
)
.with(RetryTransientMiddleware::new_with_policy(
custom_retry_policy,
))
.build();
let custom_config = Config::builder()
.api_key(
std::env::var("OPENAI_API_KEY")
.expect("OPENAI_API_KEY environment variable must be set"),
)
.http_client(custom_http_client)
.build();
let custom_client = Client::builder(custom_config)?.build();
println!("Sending request with custom retry policy (up to 5 retries)...");
let builder = custom_client.chat_simple("Explain quantum computing in one sentence.");
match custom_client.send_chat(builder).await {
Ok(response) => {
println!("\nSuccess! Response received:");
if let Some(content) = response.content() {
println!("{content}");
}
}
Err(e) => {
eprintln!("\nError after all retries: {e}");
}
}
println!("\n3. Using builder pattern with retry middleware");
let builder = custom_client
.responses()
.user("What are the three laws of robotics?")
.max_completion_tokens(200)
.temperature(0.7);
let response = custom_client.send_responses(builder).await?;
println!("\nResponse received:");
if let Some(content) = response.content() {
println!("{content}");
}
println!("\nToken usage:");
if let Some(usage) = response.usage() {
let prompt = usage.prompt_tokens;
let completion = usage.completion_tokens;
let total = usage.total_tokens;
println!(" Prompt tokens: {prompt}");
println!(" Completion tokens: {completion}");
println!(" Total tokens: {total}");
}
println!("\n=== Example completed successfully! ===");
println!("\nKey benefits of using reqwest-middleware:");
println!(" - Automatic retry of transient failures");
println!(" - Exponential backoff to avoid overwhelming servers");
println!(" - Composable middleware for logging, metrics, etc.");
println!(" - Transparent to application code - works with any request");
Ok(())
}