I have a job processing app that exposes a web API to add jobs and process them but the API request should not wait for the job to finish (it could take a while). I use Server-Sent Events to broadcast the job result. This means the main API server is executing inside main
with #[tokio::main]
, but where should I be running the job executor? In the job executor, I will have plenty of waiting: things like downloading. They will interfere with the web API server. The crucial question is how do I even start both executions in parallel?
In this scenario, you need to create a separate thread with thread::spawn
inside which you will create a Tokio executor. The error you get is that inside your second thread, there is no Tokio executor (runtime). You need to create one manually and tell it to run your tasks. The easier way is to use the Runtime
API:
use tokio::runtime::Runtime; // 0.2.23
// Create the runtime
let rt = Runtime::new().unwrap();
// Spawn a future onto the runtime
rt.spawn(async {
println!("now running on a worker thread");
});
In your main thread, an executor is already available with the use of #[tokio::main]
. Prior to the addition of this attribute, the runtime was created manually.
If you want to stick with the async/await philosophy, you can use join
:
use tokio; // 0.2.23
#[tokio::main]
async fn main() {
let (_, _) = tokio::join!(start_server_listener(), start_job_processor());
}
This is why most answers are questioning your approach. Although very rare, I believe there are scenarios where you want an async runtime to be on another thread while also having the benefit to manually configure the runtime.