use errcraft::{craft, ErrFrame};
use std::time::Duration;
async fn fetch_user_data(user_id: u64) -> Result<String, ErrFrame> {
tokio::time::sleep(Duration::from_millis(100)).await;
Err(craft!("Failed to fetch user data")
.context("user_id", user_id)
.context("service", "user-api")
.context_text("Remote service returned 404"))
}
async fn get_user_profile(user_id: u64) -> Result<String, ErrFrame> {
fetch_user_data(user_id).await.map_err(|e| {
craft!("Profile retrieval failed")
.context("user_id", user_id)
.with_source(e)
})
}
async fn sync_user_data(user_id: u64) -> Result<(), ErrFrame> {
get_user_profile(user_id).await.map_err(|e| {
craft!("User data synchronization failed")
.context("operation", "sync")
.context("timestamp", chrono::Utc::now().to_rfc3339())
.with_source(e)
})?;
Ok(())
}
#[tokio::main]
async fn main() {
println!("=== errcraft Async API Example ===\n");
println!("Example 1: Async fetch error");
if let Err(e) = fetch_user_data(42).await {
e.eprint();
}
println!("\n{}\n", "=".repeat(60));
println!("Example 2: Nested async error chain");
if let Err(e) = sync_user_data(123).await {
e.eprint();
}
println!("\n{}\n", "=".repeat(60));
println!("Example 3: Concurrent operations");
let tasks = vec![
tokio::spawn(fetch_user_data(1)),
tokio::spawn(fetch_user_data(2)),
tokio::spawn(fetch_user_data(3)),
];
for (i, task) in tasks.into_iter().enumerate() {
match task.await {
Ok(Ok(_)) => println!("Task {} succeeded", i + 1),
Ok(Err(e)) => {
println!("Task {} failed:", i + 1);
e.eprint();
println!();
}
Err(e) => println!("Task {} panicked: {}", i + 1, e),
}
}
}