Timeout interruption #2598
-
SummaryHello I'm new with Rust and axum, I'm trying to understand how the timeout works with axum. #[tokio::main]
async fn main() {
let timeout_layer = ServiceBuilder::new()
.layer(HandleErrorLayer::new(handle))
.timeout(Duration::from_secs(1));
let app = Router::new().route("/", get(|| async {
// sleep(Duration::from_secs(5)).await; <------ This causes timeout
for _ in 1..80_000 { // <------- This is not causing timeout, it takes 5 seconds to finish.
println!("Giga loop");
}
})).layer(timeout_layer);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
async fn handle(_err: BoxError) -> (StatusCode, String) {
println!("Handle error");
(StatusCode::REQUEST_TIMEOUT, "Request took too long".to_string())
} I want to make sure I understand why the timeout happens when the commented sleep run and why it doesn't on the loop.
To get he loop interrupted I need to wrap it around some async task, correct? If you have any explanation or links I appreciate! axum version0.7.4 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Yes, your explanation sounds about right. When the task with the long loop is polled, it blocks the async task which also contains the timeout until it is done. Two obvious solutions come to mind, either you use |
Beta Was this translation helpful? Give feedback.
Yes, your explanation sounds about right. When the task with the long loop is polled, it blocks the async task which also contains the timeout until it is done. Two obvious solutions come to mind, either you use
tokio::task::spawn_blocking
(generally preferable for CPU-bound work), or you calltokio::task::yield_now().await
periodically within your loop to give back control to give control back to the async runtime / let other futures that are part of the same task make progress.