#[cfg(feature = "async")]
use error_forge::{AppError, AsyncForgeError, AsyncResult};
#[cfg(feature = "async")]
use std::time::Duration;
#[cfg(feature = "async")]
async fn fetch_data(endpoint: &str) -> AsyncResult<String, AppError> {
tokio::time::sleep(Duration::from_millis(100)).await;
if endpoint.contains("invalid") {
return Err(
AppError::network(endpoint, None::<Box<dyn std::error::Error + Send + Sync>>)
.with_retryable(true)
.with_status(503),
);
}
Ok(format!("Data from {}", endpoint))
}
#[cfg(feature = "async")]
async fn process_data_with_retry(
endpoint: &str,
max_retries: usize,
) -> AsyncResult<String, AppError> {
let mut retries = 0;
let mut backoff = 100;
loop {
let result = fetch_data(endpoint).await;
match result {
Ok(data) => return Ok(data),
Err(err) if err.is_retryable() && retries < max_retries => {
println!("Error occurred: {}. Retrying in {}ms...", err, backoff);
let _ = err.handle_async().await;
tokio::time::sleep(Duration::from_millis(backoff)).await;
retries += 1;
backoff *= 2; }
Err(err) => {
return Err(err);
}
}
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
#[cfg(feature = "async")]
{
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(async {
println!("Testing async error handling with retry logic:");
match process_data_with_retry("api.example.com/users", 3).await {
Ok(data) => println!("Success: {}", data),
Err(e) => println!("Failed: {}", e),
}
match process_data_with_retry("api.example.com/invalid", 3).await {
Ok(data) => println!("Success: {}", data),
Err(e) => println!("Failed after retries: {}", e),
}
});
}
#[cfg(not(feature = "async"))]
{
println!("Async feature is not enabled. Run with --features=async to see this example.");
}
Ok(())
}