async-book
async-book copied to clipboard
Timeout question
Hi! First of all, thank you for a great resource!
Then, I made a timeout
future, extending on the TimerFuture and Executor from the current sections of the book.
pub enum Result<T> { Completed(T), TimedOut }
pub async fn timeout<T>(future: impl Future<Output=T> + Unpin, timeout: Duration) -> Result<T> {
let (abort_handle, abort_registration) = AbortHandle::new_pair();
let abortable_future = Abortable::new(future, abort_registration);
let mut fused_future = abortable_future.fuse();
let fused_timer = TimerFuture::new(timeout).fuse();
pin_mut!(fused_timer);
// could cause a race if timer and future end at the same time?
let result: Result<T> = select! {
res_1 = fused_future => Result::Completed(res_1.unwrap()),
_ = fused_timer => Result::TimedOut,
};
if let Result::TimedOut = result {
abort_handle.abort();
}
result
}
I apologize for any glaring redundancies, I'm new to Rust.
My question is, before I used an async
function for the timeout implementation I tried to make a TimeoutFuture
implementation similar to the TimerFuture
from scratch, and ran into the issue of not being able to pass through / spawn the passed in timed future from inside the TimeoutFuture
implementation.
Is there any canonical way to get around this? For a Future implementation to spawn another Future?
Also, secondly, my AbortHandle doesn't seem to work, I assume this is because it requires some support from the Executor::run
function?
Hope to see some new chapters!
PS: The HTTP server has a nice cleaner version with hyper 1.30.0
without the need for compat
.
use std::convert::Infallible;
use std::net::SocketAddr;
use hyper::{Body, Request, Response, Server,
service::{make_service_fn, service_fn}};
async fn req_handler(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
Ok(Response::new(Body::from("hello, world!.")))
}
async fn run_server(addr: SocketAddr) {
println!("listening on http://{}", addr);
let service = make_service_fn(|_conn| async {
Ok::<_, Infallible>(service_fn(req_handler))
});
let server = Server::bind(&addr).serve(service);
if let Err(e) = server.await {
eprintln!("server error: {}", e);
}
}
// as per hyper 1.30.0 release notes recommendation
#[tokio::main]
async fn main() {
let addr = SocketAddr::from(([127, 0, 0, 1], 7878));
run_server(addr).await;
}