Reputation: 6753
In one of my actix-web handlers I want to call a function that run in the background and immediately return a response to the user:
async fn heavy_computation() -> {
// do some long running computation
}
async fn index(req: HttpRequest) -> impl Responder {
// start computation
heavy_computation();
// render and return template
let out context = Context::new();
context.insert("foo", "bar");
render_template("my_template.html", &context)
// computation finishes
}
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(web::resource("/").route(web::get().to(index)))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
If I await
the future the response isn't done until after the computation and if I don't await
it, the function isn't executed at all.
Upvotes: 4
Views: 3756
Reputation: 35512
Assuming that you're using tokio
as your async runtime, you can spawn two tasks using tokio::task::spawn
then join them with tokio::join
:
use tokio::task;
use tokio::time;
use std::time::Duration;
async fn heavy_computation() {
time::delay_for(Duration::from_millis(2000)).await;
println!("heavy computation finished");
}
async fn light_computation() {
time::delay_for(Duration::from_millis(500)).await;
println!("light computation finished");
}
#[tokio::main]
async fn main() {
let heavy = task::spawn(heavy_computation());
println!("computation started");
let light = task::spawn(async move {
for _ in 0..3 {
light_computation().await;
}
});
let (a, b) = tokio::join!(heavy, light);
// use the results so the compiler doesn't complain
a.unwrap();
b.unwrap();
}
Upvotes: 3