My goal is to do some database queries from the async controller, then return the answer.
I’m playing with the example project, for now just simulating the DB queries with a sleep, but what I noticed is that whatever I do, the REST interface won’t even start the sleep of the second query until the first one finishes.
E.g.: If I call the REST interface from one tab in the browser, then 1 second later again from an another tab, I’d expect that the second one gets the reply too in 10 seconds, but actually it’s 19.
Also it doesn’t seem to use the “database-io” pool either:
You should use the execution context named “database-io”, you are actually passing the ActorSystem’s dispatcher, the same that is used to render, thus blocking the route
implicit val dbCtx: ExecutionContext = actorSystem.dispatchers.lookup("database-io")
private def getFutureMessage(): Future[String] = {
val defaultThreadPool = Thread.currentThread().getName;
println(s"""1: $defaultThreadPool""")
val promise: Promise[String] = Promise[String]()
actorSystem.scheduler.scheduleOnce(0 second) {
val blockingPool = Thread.currentThread().getName;
println(s"""2: $blockingPool""")
Thread.sleep(10000)
promise.success("Hi!")
}(dbCtx)
promise.future
}
Note that if its the only ExecutionContext in this scope you dont need to pass it to the Promise, if its not the only one then its better to not have it as implicit and use it directly as demonstrated
Try using curl instead of the browser. I also run into this exact issue some time ago when testing from Chrome, and it turned out that the browser itself does not send any subsequent requests to the same endpoint until it receives at least one successful response. In other words, you code might not even receive the second request until it responds to the first one, because the browser doesn’t send it.