use std::time::Duration;
use fetch::fake::{FakeDeps, FakeHandler};
use fetch::{HttpClient, HttpResponseBuilder};
use http::StatusCode;
use ohno::ErrorExt;
const FAILING_HOST: &str = "https://failing.example.com";
const HEALTHY_HOST: &str = "https://healthy.example.com";
#[tokio::main]
async fn main() -> Result<(), ohno::AppError> {
let fake_handler = FakeHandler::from_fn(|req| {
let status = if req.uri().host() == Some("failing.example.com") {
StatusCode::INTERNAL_SERVER_ERROR
} else {
StatusCode::OK
};
HttpResponseBuilder::new_fake().status(status).build()
});
let client = HttpClient::builder_fake(fake_handler, FakeDeps::default())
.standard_pipeline(|pipeline, _| {
pipeline
.retry(|retry| retry.max_retry_attempts(0))
.breaker(|breaker| {
breaker
.min_throughput(5)
.failure_threshold(0.5)
.break_duration(Duration::from_secs(30))
})
})
.build();
println!("--- Sending requests to {FAILING_HOST} (expect 500s) ---");
for i in 1..=10 {
let result = client.get(FAILING_HOST).fetch().await;
match result {
Ok(resp) => println!(" request {i}: {}", resp.status()),
Err(e) => println!(" request {i}: error — {}", e.message()),
}
}
println!("\n--- Breaker should be open for {FAILING_HOST} ---");
let result = client.get(FAILING_HOST).fetch().await;
match result {
Ok(resp) => println!(" unexpected success: {}", resp.status()),
Err(e) => println!(" rejected: {}", e.message()),
}
println!("\n--- Sending request to {HEALTHY_HOST} (should succeed) ---");
let response = client.get(HEALTHY_HOST).fetch().await?;
println!(" response: {}", response.status());
assert_eq!(
response.status(),
StatusCode::OK,
"healthy host should not be affected by the failing host's breaker"
);
println!("\nDone — circuit breaker isolation between origins is working.");
Ok(())
}