use std::time::{Duration, Instant};
use hpx::{
Client,
delay::{DelayLayer, JitterDelayLayer},
};
#[tokio::main]
async fn main() -> Result<(), hpx::Error> {
basic_jitter_delay().await?;
println!("\n{}\n", "=".repeat(60));
conditional_jitter_delay().await?;
println!("\n{}\n", "=".repeat(60));
conditional_fixed_delay().await?;
Ok(())
}
async fn basic_jitter_delay() -> Result<(), hpx::Error> {
println!("=== Basic Jittered Delay ===\n");
let client = Client::builder()
.layer(JitterDelayLayer::new(Duration::from_secs(1), 0.5))
.cert_verification(false)
.build()?;
let url = "https://httpbin.io/get";
println!(
"Sending 3 requests to {} using JitterDelayLayer(1s ± 50%)",
url
);
println!("Expected delay range: [0.5s, 1.5s]\n");
let mut prev_start = Instant::now();
for i in 1..=3 {
let start = Instant::now();
let delta = start.duration_since(prev_start);
if i > 1 {
println!(
"Request #{}: delay since last = {:.3}s",
i,
delta.as_secs_f64()
);
} else {
println!("Request #{}: starting...", i);
}
let _ = client.get(url).send().await?;
println!(
"Request #{}: completed in {:.3}s\n",
i,
start.elapsed().as_secs_f64()
);
prev_start = start;
}
println!("Notice how the delays vary randomly within the [0.5s, 1.5s] range.");
Ok(())
}
async fn conditional_jitter_delay() -> Result<(), hpx::Error> {
println!("=== Conditional Jittered Delay (using `JitterDelayLayer::when`) ===\n");
let client = Client::builder()
.layer(JitterDelayLayer::new(Duration::from_millis(800), 0.3).when(
|req: &http::Request<_>| {
req.method() == http::Method::POST
},
))
.cert_verification(false)
.build()?;
const BASE_URL: &str = "https://httpbin.io";
println!("POST requests will have jittered delay (800ms ± 30%)");
println!("GET requests will pass through immediately\n");
for i in 1..=4 {
let start = Instant::now();
if i % 2 == 1 {
let url = format!("{BASE_URL}/get");
println!("Request #{}: GET {}", i, url);
let _ = client.get(&url).send().await?;
} else {
let url = format!("{BASE_URL}/post");
println!("Request #{}: POST {}", i, url);
let _ = client.post(&url).send().await?;
}
println!(
"Request #{}: completed in {:.3}s ({})\n",
i,
start.elapsed().as_secs_f64(),
if i % 2 == 1 { "no delay" } else { "with delay" }
);
}
println!("Notice: GET requests complete quickly, POST requests have ~800ms delay.");
Ok(())
}
async fn conditional_fixed_delay() -> Result<(), hpx::Error> {
println!("=== Conditional Fixed Delay (using `DelayLayer::when`) ===\n");
let client = Client::builder()
.layer(
DelayLayer::new(Duration::from_secs(1)).when(|req: &http::Request<_>| {
req.uri().path().starts_with("/delay")
}),
)
.cert_verification(false)
.build()?;
const BASE_URL: &str = "https://httpbin.io";
println!("Requests to /delay/* will have 1s fixed delay");
println!("Other requests will pass through immediately\n");
let endpoints = ["/get", "/delay/0"];
for (i, endpoint) in endpoints.iter().enumerate() {
let url = format!("{BASE_URL}{endpoint}");
let start = Instant::now();
println!("Request #{}: GET {}", i + 1, url);
let _ = client.get(&url).send().await?;
let elapsed = start.elapsed().as_secs_f64();
let has_delay = endpoint.starts_with("/delay");
println!(
"Request #{}: completed in {:.3}s ({})\n",
i + 1,
elapsed,
if has_delay { "with delay" } else { "no delay" }
);
}
println!("Notice: /get completes quickly, /delay/* has additional 1s delay.");
Ok(())
}