Reputation: 695
I'm using Scala / Slick 3.1 (This is all through the spray-slick-swagger typesafe activator) and have 4 different queries running that I want to return as one object. I'm trying to compose all the futures together into one future.
It works, but the problem is if a query fails (I.e., we search for something that doesn't exist) there is a runtime exception.
What I think I really is to fail the whole thing if one query fails and ultimately return a Future[Option]
The whole thing is hooked up through spray
so the query code looks like :
// .. snip .. FindById()
val a = db.run(q1.result) // Future[Seq[Tuple]]]
val b = db.run(q2.result)
val c = db.run(q3.result)
val d = db.run(q4.result)
// compose the futures together into one future
val res = for {
resA <- a
resB <- b
resC <- c
resD <- d
} yield {
PhoneMerged(resA.head._1, resA.head._2, resB.map( x => FeaturesSimple(x.featurename)).toList, resD.map(x => FeaturesvaluepairSimple(x.featuretype, x.featurevalue)).toList,
resC.map(x => IncludedaccessorySimple(x.accessoryvalue)).toList, createPhoneImage(resA.head._1.devicemcd))
}
It gets called with
onComplete((modules.phonesDAA ? FindById(id)).mapTo[Future[PhoneMerged]]) {
case Success(phoneOption) => {
println(phoneOption)
complete(phoneOption)
}
case Failure(ex) => {
println("uh oh")
complete("{}")
}
}
ultimately I want to return either the JSON serialized PhoneMerged object ( which works if I search for a valid id ) or "{}" empty json ...
Anybody have any thoughts on how to properly process the result / handle the error ?
Upvotes: 0
Views: 570
Reputation: 381
You could make the FindById
function return a Future[Option[PhoneMerged]]
and handle the failure case inside using a Future combinator such as recover
.
For example:
val a = db.run(q1.result)
// Future[Seq[Tuple]]]
val b = db.run(q2.result)
val c = db.run(q3.result)
val d = db.run(q4.result)
// compose the futures together into one future
val res = for {
resA <- a
resB <- b
resC <- c
resD <- d
} yield {
Some(PhoneMerged(resA.head._1, resA.head._2, resB.map(x => FeaturesSimple(x.featurename)).toList, resD.map(x => FeaturesvaluepairSimple(x.featuretype, x.featurevalue)).toList,
resC.map(x => IncludedaccessorySimple(x.accessoryvalue)).toList, createPhoneImage(resA.head._1.devicemcd)))
} recover {case e: YourExceptionType => None}
Upvotes: 1