Created
October 21, 2024 19:15
-
-
Save mrnugget/571dd2560b910f33385fea99084576ea to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use anyhow::Result; | |
use std::convert::Infallible; | |
use warp::Filter; | |
struct Deferred<T: FnOnce()> { | |
task: Option<T>, | |
} | |
impl<T: FnOnce()> Deferred<T> { | |
fn abort(&mut self) { | |
self.task.take(); | |
} | |
} | |
impl<T: FnOnce()> Drop for Deferred<T> { | |
fn drop(&mut self) { | |
if let Some(task) = self.task.take() { | |
task(); | |
} | |
} | |
} | |
fn defer<T: FnOnce()>(f: T) -> Deferred<T> { | |
Deferred { task: Some(f) } | |
} | |
async fn send_request(url: &str, metrics: &mut Metrics) -> Result<String> { | |
let mut finish = defer(|| metrics.requests += 1); | |
let request = reqwest::get(url); | |
tokio::select! { | |
response = request => { | |
let response = response?; | |
let body = response.text().await?; | |
Ok(body) | |
} | |
_ = tokio::time::sleep(std::time::Duration::from_millis(2500)) => { | |
finish.abort(); | |
Err(anyhow::anyhow!("timeout")) | |
} | |
} | |
} | |
struct Metrics { | |
requests: usize, | |
} | |
#[tokio::main] | |
async fn main() { | |
let routes = warp::path::param().and_then(sleepy); | |
tokio::spawn(warp::serve(routes).run(([127, 0, 0, 1], 3030))); | |
let mut metrics = Metrics { requests: 0 }; | |
for (i, sleep) in (1..5).into_iter().enumerate() { | |
println!("Sending request #{i}. sleep={sleep}s"); | |
let url = format!("http://127.0.0.1:3030/{sleep}"); | |
let result = send_request(&url, &mut metrics).await; | |
println!("request #{i} result = {result:?}"); | |
println!("metrics.requests = {}", metrics.requests); | |
println!("-----------"); | |
} | |
} | |
async fn sleepy(Seconds(seconds): Seconds) -> Result<impl warp::Reply, Infallible> { | |
tokio::time::sleep(std::time::Duration::from_secs(seconds)).await; | |
Ok(format!("I waited {} seconds!", seconds)) | |
} | |
struct Seconds(u64); | |
impl std::str::FromStr for Seconds { | |
type Err = (); | |
fn from_str(src: &str) -> Result<Self, Self::Err> { | |
src.parse::<u64>().map_err(|_| ()).map(Seconds) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment