Annotated version
use std::time::Duration; use color_eyre::eyre; struct Deferred<T: FnOnce()> { task: Option<T>, } impl<T: FnOnce()> Deferred<T> { fn abort(&mut self) { println!("I AM ABORTING"); 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) -> eyre::Result<()> { let mut finish = defer(|| println!("I am done here")); // this pattern is amazing, this is only called when there is no timeout // otherwise abort is called let request = reqwest::get(url); tokio::select! { response = request => { let response = response?; let body = response.text().await?; println!("{:?}", &body[..20]); } _ = tokio::time::sleep(Duration::from_millis(1000)) => { finish.abort(); return Err(eyre::eyre!("timeout")) } } Ok(()) } #[tokio::main] async fn main() { println!("MAKING REQ"); send_request("https://www.google.com").await.unwrap(); }