As I have been developing with Play 2 for the first time, I find I do something like this a lot in my controllers (one of the simpler examples):
val promUser = Akka.future(UserService.findByUsername(access.username))
Async(
promUser.map {
_.map{
user => {
val promService = Akka.future(ServiceService loadOnlyWithUser (id,user.id.get))
Async(
promService.map { _.map { service =>
Ok(toJson(service))
}.getOrElse(BadRequest("not accessible"))}
)
}
}.getOrElse {
BadRequest("unauthorised")
}
}
)
Would it be better to have a single future? eg:
val promService = Akka.future{
val userOption = UserService.findByUsername(access.username)
userOption.map( user => {
ServiceService loadOnlyWithDeveloper (id,user.id.get)
}).getOrElse(None)
}
Async(
promService.map { _.map { service =>
Ok(toJson(service))
}.getOrElse(BadRequest("unauthorised"))}
)
I’m thinking on the one hand many futures/returns to the controller may add overhead, on the over hand group the calls into one future will be more readable but lead to larger “threads” running in the Akka system. For much larger jobs I have an extra Akka system, so these would only encompass maybe max of 4 SQL transactions. As far as I can work out from apache bench, there isn’t any difference between the examples above…. Is there anything Im missing?
There isn’t any difference in performance with your examples because they are equivalent.
When you write:
It does not start to evaluate that
Future, it is only executed when you then map it.As I understand it, you need to think about futures composition. This is a really nice documentation that I would recommend: http://docs.scala-lang.org/sips/pending/futures-promises.html
To answer your question then, I don’t think it makes a difference if you have multiple Futures, one for each DB access, if you need to perform a bunch of queries in sequence. E.g. retrieve a record, then delete it.
Where you can take advantage of Futures (besides making your app non-blocking) is to take advantage of the for-comprehension syntax so that you can run two or more asynchronous Futures at the same time, e.g.
Also, I would recommend using
flatMapto compose your Futures together, rather than having multipleAsync{}blocks. This way you will effectively flatten your multiple Futures,Future[Future[Result]]into a single Future that can be anAsyncResult.