Scala map over a Future - scala

In the following example, what is the expected behaviour?
import scala.concurrent.ExecutionContext.Implicits.global
val someFuture = Future { 1+1 }.map(elem => {
println("mapping immediately")
elem.toString
})
someFuture.onComplete {
case scala.util.Success(value) => println(s"Got the callback = $value")
case Failure(e) => e.printStackTrace()
}
Is the following output always guaranteed?
mapping immediately
Got the callback = 2

It depends.
val someFuture = Future { 1+1 }.map(elem => {
println("mapping immediately")
elem.toString
})
someFuture will be executed eagerly and the println will be executed.
someFuture.onComplete {
case scala.util.Success(value) => println(s"Got the callback = $value")
case Failure(e) => e.printStackTrace()
}
onComplete is an event listener for a Future. This is called only when this future is completed, either through an exception, or a value, to apply the provided function.
Therefore, it will always execute after the execution of the someFuture.
Assuming that the someFuture is not going to fail, the order
`mapping immediately
Got the callback = 2`
is guaranteed.
For what ever reason, if there's an exception thrown, then the result would change. In that case Got the callback = 2 will not be printed and mapping immediately may or may not be printed.
Hope this helps.

Related

Can a Future throw an exception caught by a caller?

When I run the code below it terminates and nothing happens, is there a way to catch the exception in future2.map ?
object TestFutures1 {
val future1 = Future {
throw new Exception("error")
}
}
object TestFutures2 extends App {
val future2 = TestFutures1.future1
future2.map { result => println(result) }
Thread.sleep(5000)
}
Generally speaking, there are two options (with some sub-options) to handle future exceptions.
You can add a callback that will be called when the future completes with an exception:
future2
.map { result => println(result) }
.onFailure { exc =>
exc.printStackTrace
}
1a. .onFailure is only used for side effects, you cannot use, for example, to handle the exception. If you want to handle in and rescue the future, you can use .recover or .recoverWith (the only different between the two is that the latter takes a function that returns a Future, while the former deals with the actual result, same idea as map vs. flatMap:
future2
.map(println)
.recover { case e =>
e.printStackTrace
"recovered"
}.map(println)
The other option is to wait for the future to complete, and access it's result:
try {
// Instead of Thread.sleep - you don't need that:
Await.result(future2, 2 seconds)
} catch { case exc =>
exc.printStackTrace
}
Except #Dima's answer, also can use onComplete to catch failure, like:
val re = future2.map { result => println(result) }
re onComplete {
case Success(s) => ...
case Failure(e) => e.printStackTrace()
}

Understanding Spray's detach directive

I'm trying to understand Spray's detach directive and whether there's any difference between using detach and using the onComplete directive. What I want to achieve is "one thread per request" where by thread I mean JVM thread ( which should be an OS thread).
So, what the difference between A and B ?
Method A:
// assume controller.divide(a,b) returns Future[Int]
val route =
path("divide" / IntNumber / IntNumber) { (a, b) =>
onComplete(controller.divide(a, b)) {
case Success(value) => complete(s"The result was $value")
case Failure(ex) => complete(InternalServerError, s"An error occurred: ${ex.getMessage}")
}
}
Method B:
// assume controller.divide(a,b) returns Int
val route = {
path("divide" / IntNumber / IntNumber) { (a,b) =>
detach(global) {
Try { controller.divide(a,b) } match {
case Success(value) => complete(s"The result was $value")
case Failure(ex) => complete(InternalServerError, s"An error occurred: ${ex.getMessage}")
}
}
} }
Cheers !
The point of detach is that you don't need your method to return a Future - that's really it.
The idea is to run items you know won't throw exceptions compactly, but without needing to block the handler thread. You should rewrite Method B as:
detach(global) {
complete(s"The result was ${controller.divide(a, b)}")
}
In the spray-routing world, the Failure case would be handled by an outer handleExceptions directive.
See Spray's `detach` Directive where the accepted answer explains very well, what
detach does and
how it uncouples from the route executing actor.

Scala waiting for sequence of futures

I was hoping code like follows would wait for both futures, but it does not.
object Fiddle {
val f1 = Future {
throw new Throwable("baaa") // emulating a future that bumped into an exception
}
val f2 = Future {
Thread.sleep(3000L) // emulating a future that takes a bit longer to complete
2
}
val lf = List(f1, f2) // in the general case, this would be a dynamically sized list
val seq = Future.sequence(lf)
seq.onComplete {
_ => lf.foreach(f => println(f.isCompleted))
}
}
val a = FuturesSequence
I assumed seq.onComplete would wait for them all to complete before completing itself, but not so; it results in:
true
false
.sequence was a bit hard to follow in the source of scala.concurrent.Future, I wonder how I would implement a parallel that waits for all original futures of a (dynamically sized) sequence, or what might be the problem here.
Edit: A related question: https://worldbuilding.stackexchange.com/questions/12348/how-do-you-prove-youre-from-the-future :)
One common approach to waiting for all results (failed or not) is to "lift" failures into a new representation inside the future, so that all futures complete with some result (although they may complete with a result that represents failure). One natural way to get that is lifting to a Try.
Twitter's implementation of futures provides a liftToTry method that makes this trivial, but you can do something similar with the standard library's implementation:
import scala.util.{ Failure, Success, Try }
val lifted: List[Future[Try[Int]]] = List(f1, f2).map(
_.map(Success(_)).recover { case t => Failure(t) }
)
Now Future.sequence(lifted) will be completed when every future is completed, and will represent successes and failures using Try.
And so, a generic solution for waiting on all original futures of a sequence of futures may look as follows, assuming an execution context is of course implicitly available.
import scala.util.{ Failure, Success, Try }
private def lift[T](futures: Seq[Future[T]]) =
futures.map(_.map { Success(_) }.recover { case t => Failure(t) })
def waitAll[T](futures: Seq[Future[T]]) =
Future.sequence(lift(futures)) // having neutralized exception completions through the lifting, .sequence can now be used
waitAll(SeqOfFutures).map {
// do whatever with the completed futures
}
A Future produced by Future.sequence completes when either:
all the futures have completed successfully, or
one of the futures has failed
The second point is what's happening in your case, and it makes sense to complete as soon as one of the wrapped Future has failed, because the wrapping Future can only hold a single Throwable in the failure case. There's no point in waiting for the other futures because the result will be the same failure.
This is an example that supports the previous answer. There is an easy way to do this using just the standard Scala APIs.
In the example, I am creating 3 futures. These will complete at 5, 7, and 9 seconds respectively. The call to Await.result will block until all futures have resolved. Once all 3 futures have completed, a will be set to List(5,7,9) and execution will continue.
Additionally, if an exception is thrown in any of the futures, Await.result will immediately unblock and throw the exception. Uncomment the Exception(...) line to see this in action.
try {
val a = Await.result(Future.sequence(Seq(
Future({
blocking {
Thread.sleep(5000)
}
System.err.println("A")
5
}),
Future({
blocking {
Thread.sleep(7000)
}
System.err.println("B")
7
//throw new Exception("Ha!")
}),
Future({
blocking {
Thread.sleep(9000)
}
System.err.println("C")
9
}))),
Duration("100 sec"))
System.err.println(a)
} catch {
case e: Exception ⇒
e.printStackTrace()
}
Even though it is quite old question But this is how I got it running in recent time.
object Fiddle {
val f1 = Future {
throw new Throwable("baaa") // emulating a future that bumped into an exception
}
val f2 = Future {
Thread.sleep(3000L) // emulating a future that takes a bit longer to complete
2
}
val lf = List(f1, f2) // in the general case, this would be a dynamically sized list
val seq = Future.sequence(lf)
import scala.concurrent.duration._
Await.result(seq, Duration.Inf)
}
This won't get completed and will wait till all the future gets completed. You can change the waiting time as per your use case. I have kept it to infinite and that was required in my case.
We can enrich Seq[Future[T]] with its own onComplete method through an implicit class:
def lift[T](f: Future[T])(implicit ec: ExecutionContext): Future[Try[T]] =
f map { Success(_) } recover { case e => Failure(e) }
def lift[T](fs: Seq[Future[T]])(implicit ec: ExecutionContext): Seq[Future[Try[T]]] =
fs map { lift(_) }
implicit class RichSeqFuture[+T](val fs: Seq[Future[T]]) extends AnyVal {
def onComplete[U](f: Seq[Try[T]] => U)(implicit ec: ExecutionContext) = {
Future.sequence(lift(fs)) onComplete {
case Success(s) => f(s)
case Failure(e) => throw e // will never happen, because of the Try lifting
}
}
}
Then, in your particular MWE, you can do:
val f1 = Future {
throw new Throwable("baaa") // emulating a future that bumped into an exception
}
val f2 = Future {
Thread.sleep(3000L) // emulating a future that takes a bit longer to complete
2
}
val lf = List(f1, f2)
lf onComplete { _ map {
case Success(v) => ???
case Failure(e) => ???
}}
This solution has the advantage of allowing you to call an onComplete on a sequence of futures as you would on a single future.
Create the Future with a Try to avoid extra hoops.
implicit val ec = ExecutionContext.global
val f1 = Future {
Try {
throw new Throwable("kaboom")
}
}
val f2 = Future {
Try {
Thread.sleep(1000L)
2
}
}
Await.result(
Future.sequence(Seq(f1, f2)), Duration("2 sec")
) foreach {
case Success(res) => println(s"Success. $res")
case Failure(e) => println(s"Failure. ${e.getMessage}")
}

In scala how to wrap a PartialFunction?

In scala, Futures have a sort of rescue function that takes a PartialFunction. This code is skipped if the Future resolved with a response but is called if a failure occurs.
I want to simple wrap the partial function in a proxy that always executes code that writes to a stat counter. At first I was thinking I would just create another PartialFunction but soon realized that does not work very well with the isDefined, then apply as I really want this to be called every time.
How do I go about proxying the PartialFunction such that my code is always called when the Future has an exception?
To summarize the comments: You can use the onFailure callback to execute some side-effecting code (logging) when a Future fails.
val future = Future(1 / 0)
future.onFailure {
case _ => println("I have seen the Future, and it doesn't look good.")
}
As #cmbaxter notes, you could also use andThen on the Future, which accepts a PartialFunction[Try[A], B] and returns the original Future. So you could apply the side-effecting function using andThen, and than recover afterwards. You could even chain them multiple times.
Future(1 / 0)
.andThen { case Failure(_) => println("Future failed.") }
.recover { case e: ArithmeticException => 0 }
.andThen { case Failure(_) => println("Tried to recover, and still failed.") }
Or a helper that always includes it:
object FutureLogger {
def apply[A](a: => A): Future[A] = Future(a).andThen {
case Failure(_) => println("FAILURE")
}
}

Getting the value out of a Future in Scala

I have the following code snippet that I use to read a record from the database and I'm using ReactiveMongo for this.
val futureList: Future[Option[BSONDocument]] = collection.find(query).cursor[BSONDocument].headOption
val os: Future[Option[Exam]] = futureList.map {
(list: Option[BSONDocument]) => list match {
case Some(examBSON) => {
val id = examBSON.getAs[Int]("id").get
val text = examBSON.getAs[String]("text").get
val description = examBSON.getAs[String]("description").get
val totalQuestions = examBSON.getAs[Int]("totalQuestions").get
val passingScore = examBSON.getAs[Int]("passingScore").get
Some(Exam(id, text, description, totalQuestions, passingScore))
}
case None => None
}
}.recover {
case t: Throwable => // Log exception
None
}
I do not want to change my method signature to return a Future. I want to get the value inside the Future and return it to the caller.
You need then to block using the awaitable object:
import scala.concurrent.duration._
val os: Future[Option[Exam]] = ???
val result = Await.result(os, 10 seconds)
result.getOrElse(/* some default */)
Note that blocking will block the thread until the future is completed or the timeout expires and an exception is thrown, note also that this kinda defeats the purpose of having async computation, but it may be ok depending on your use case.
If you don't need the result immediately you can attach a callback using onComplete
os onComplete {
case Success(someOption) => myMethod(someOption)
case Failure(t) => println("Error)
}
Note that onComplete will be fired only when the future is completed so the result is not immediately accessible, also the return type is Unit.