Future[Try[Book]] vs Future[Book] in Scala? - scala

I was suggested to use Future[Book] rather than Future[Try[Book]] in a pull request review.
Why is that?
If I use Future[Book], then how I can convert Success or Failure. Is it not clear to me at all.
If we use Future[Book], we are completely losing the notion of success and failure in Scala.

In Scala, the resulting value of a future is wrapped in either a Success or Failure type, which is a type of Try. Hence, the value in a Future is always an instance of one of the Try types: Success or Failure.
Since these are Try types, you can register a callback on a future which accepts a Try type. An example is to use the onComplete which takes a callback function of type Try[T] => U and returns a Unit.
import scala.util.{Success, Failure}
val f: Future[List[String]] = Future {
session.getUserNamesFromDatabase
}
f onComplete {
case Success(users) => for (user <- users) println(user)
case Failure(t) => println("An error has occurred: " + t.getMessage)
}
The benefit of a callback on a future is that it can complete without blocking the client. So the callback can execute completely asynchronously.
Note: that the onComplete method has a unit return type. So it cannot be chained.

Related

Transform Future[T] to Future[Try[T]]

I am trying to understand following answer How to carry on executing Future sequence despite failure?.
(Hope thats not a down vote worthy as i am trying to understand the code here.)
I dont understand how mapValue is transforming Future[T] to Future[Try[T]]
def mapValue[T]( f: Future[T] ): Future[Try[T]] = {
val prom = Promise[Try[T]]()
f onComplete prom.success
prom.future
}
the line f onComplete prom.success, what is it doing. My understanding was prom.success has to take an object of type Try[T] but here it does not do that. Also there is no assignment to f which transforms Future[T] to Future[Try[T]].
Moreover, anThen on Future is supposed to be a sideffect and is supposed to return the same future value that came into it, so not sure how does the transformation happen.
The f onComplete prom.success line is parsed by Scala compiler as following:
Dots and parentheses can be ommited in some cases, so f onComplete x is a way to write f.onComplete(x).
Compiler sees that onComplete method takes as argument function f: Try[T] => U. You also passed a function as an argument, Promise#success, which has a compatible signature.
So what the method is doing is creating a new Promise (writeable future) of type Try[T], and completing that promise with wrapped Try[T] as original future completes. Then it's returns new Future[Try[T]] obtained from promise.
To expand on Maxim's answer, f onComplete prom.success can be re-written as:
f.onComplete(prom.success)
or
f.onComplete(prom.success(_))
or
f.onComplete { resultOfFutureAsTry =>
prom.success(resultOfFutureAsTry)
}
prom.success sets the success value of the promise. Thus, no matter what happens inside the original future f, (an exception is thrown, or the future completes successfully), the new future (returned by prom.future, and created after the original future is completed) is always a successful future. Sometimes that successful future contains a Failure[T], and sometimes a Success[T].
Side note: Often, f.onComplete is used more like this:
f.onComplete {
case Success(x) => println(s"Yay, $x worked!")
case Failure(ex) => println(s"Darn, it failed: $ex")
}
But this is just a convenient way to write a function f: Try[T] => U.

Scala: failing a Future based on a Future#collect

WS.post returns a Future[Response], but I want a Future[Data] so I'm using Future.collect for that purpose.
private def getDataFuture(data: String): Future[JsValue] =
initAuthenticatedRequest().post(body).collect {
case response => response.json(0)
}.recoverWith {
case NonFatal(_) => getDataFuture(data)
}
However, sometimes response.json(0) returns a bad value because I receive an empty json. I expected this to cause the Future to fail and do the recoverWith, but that didn't happen.
Do I need to do branching within the collect case?
How can I handle this more elegantly? I imagined that Future would have provisions for this.
You must use
initAuthenticatedRequest().post(body).map(_.json.as[JsArray])
json.as[JsArray] casts json to JsArray or throws exception, which can be handled with recoverWith

Difference between scala.concurrent.onComplete and akka.http.scaladsl.server.directives.onComplete

In scala concurrent package, there is onComplete method which returns nothing while in akka-http directives, it returns the Directive1.
Is that the only difference? I sometimes got confused on those two methods.
These methods are different in what they aim to accomplish, but they are related in that the akka http onComplete is meant to work with the completion of a Future in order to complete the routing of a request.
The concurrent onComplete is a method on a Future that is meant to perform some sort of side effecting when the Future has completed. There are a lot of other methods on a Future like map, flatMap and filter that will produce another Future as you go through a series of transforms, but onComplete returns nothing, and is sort of a "dead end" in the processing of that Future.
An example of using onComplete while also showing how something like map can be used to change the Future is as follows:
val fut1 = Future{"1"} // A Future[String]
val fut2 = fut1.map(_.toInt) // Now a Future[Int]
fut2.onComplete{
case util.Success(i) => println(s"success: $i")
case util.Failure(ex) => ex.printStackTrace()
}
val badFut1 = Future{"A"}
val badFut2 = badFut.map(_.toInt) //Will be failed
badFut2.onComplete{
case util.Success(i) => println(s"success: $i")
case util.Failure(ex) => ex.printStackTrace()
}
In the first case, we will hit the success case as "1" can be mapped into an Int. In the second example, we will hit the error case as "A" cannot be mapped to an Int. Either way, you can see that something like map can be used to create a new transformed future while onComplete can be used to do something based on the final result of that Future.
In Akka Http, you sometimes need to create Route definitions that need to do something asynchronously. In that case, you need to complete the route when that asynchronous task completed. A Route itself needs to be fully defined in order to compile, so you can't leverage the existing onComplete on a Future because that returns nothing and that would render the definition of that Route as incomplete. Therefore, the guys at Akka defined an onComplete directive that will snap into a routing tree and work with a Future, returning a Directive that will fully define the tree for that Route as oppose to leaving it open ended as the Future.onComplete would. An example:
val myRoute =
get{
val fut = myActor ? "foo"
onComplete(foo){
case util.Success(_) => complete(StatusCodes.OK)
case util.Failure(ex) => complete(StatusCodes.InternalServerError)
}
}
So here, I'm making a request to an Actor using ask (?) and I get a Future back. I still need to produce something that completes the Route I am defining. If I did something like this:
val myRoute =
get{
val fut = myActor ? "foo"
fut.onComplete{
case util.Success(_) => complete(StatusCodes.OK)
case util.Failure(ex) => complete(StatusCodes.InternalServerError)
}
}
It worn't work because the onComplete here is the one from the Future and not the directive, and that returns Unit and my Route won't be full defined and won't compile.
So the onComplete directive is there to allow you to define a Route based on the completion of a Future which you can't do properly with the pre-existing onComplete from Future itself.

Do Futures always end up not returning anything?

Given that we must avoid...
1) Modifying state
2) Blocking
...what is a correct end-to-end usage for a Future?
The general practice in using Futures seems to be transforming them into other Futures by using map, flatMap etc. but it's no good creating Futures forever.
Will there always be a call to onComplete somewhere, with methods writing the result of the Future to somewhere external to the application (e.g. web socket; the console; a message broker) or is there a non-blocking way of accessing the result?
All of the information on Futures in the Scaladocs - http://docs.scala-lang.org/overviews/core/futures.html seem to end up writing to the console. onComplete doesn't return anything, so presumably we have to end up doing some "fire-and-forget" IO.
e.g. a call to println
f onComplete {
case Success(number) => println(number)
case Failure(err) => println("An error has occured: " + err.getMessage)
}
But what about in more complex cases where we want to do more with the result of the Future?
As an example, in the Play framework Action.async can return a Future[Result] and the framework handles the rest. Will it eventually have to expect never to get a result from the Future?
We know the user needs to be returned a Result, so how can a framework do this using only a Unit method?
Is there a non-blocking way to retrieve the value of a future and use it elsewhere within the application, or is a call to Await inevitable?
Best practice is to use callbacks such as onComplete, onSuccess, onFailure for side effecting operations, e.g. logging, monitoring, I/O.
If you need the continue with the result of of your Future computation as opposed to do a side-effecting operation, you should use map to get access to the result of your computation and compose over it.
Future returns a unit, yes. That's because it's an asynchronous trigger. You need to register a callback in order to gather the result.
From your referenced scaladoc (with my comments):
// first assign the future with expected return type to a variable.
val f: Future[List[String]] = Future {
session.getRecentPosts
}
// immediately register the callbacks
f onFailure {
case t => println("An error has occurred: " + t.getMessage)
}
f onSuccess {
case posts => for (post <- posts) println(post)
}
Or instead of println-ing you could do something with the result:
f onSuccess {
case posts: List[String] => someFunction(posts)
}
Try this out:
import scala.concurrent.duration._
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
val f: Future[Int] = Future { 43 }
val result: Int = Await.result(f, 0 nanos)
So what is going on here?
You're defining a computation to be executed on a different thread.
So you Future { 43 } returns immediately.
Then you can wait for it and gather the result (via Await.result) or define computation on it without waiting for it to be completed (via map etc...)
Actually, the kind of Future you are talking about are used for side-effects. The result returned by a Future depends its type :
val f = Future[Int] { 42 }
For example, I could send the result of Future[Int] to another Future :
val f2 = f.flatMap(integer => Future{ println(integer) }) // may print 42
As you know, a future is a process that happens concurrently. So you can get its result in the future (that is, using methods such as onComplete) OR by explicitly blocking the current thread until it gets a value :
import scala.concurrent.Await
import akka.util.Timeout
import scala.concurrent.duration._
implicit val timeout = Timeout(5 seconds)
val integer = Await.result(Future { 42 }, timeout.duration)
Usually when you start dealing with asynchronous processes, you have to think in terms of reactions which may never occur. Using chained Futures is like declaring a possible chain of events which could be broken at any moment. Therefore, waiting for a Future's value is definitely not a good practice as you may never get it :
val integer = Await.result(Future { throw new RuntimeException() }, timeout.duration) // will throw an uncaught exception
Try to think more in terms of events, than in procedures.

Exception Passing Through scala.concurrent.Future?

Is it possible for an exception to be thrown, escaping the Future context?
Since a Future "evaluates" as soon as it's defined:
is it possible for the definition of a Future to throw an exception, passing through the Future context?
scala> Future { Thread.sleep(3000); println("3 seconds elapsed"); 100 }
res2: scala.concurrent.Future[Int] =
scala.concurrent.impl.Promise$DefaultPromise#56113384
scala> 3 seconds elapsed
I could not come up with such an example.
scala> Future { throw new Exception("Foo!") }
res3: scala.concurrent.Future[Nothing] =
scala.concurrent.impl.Promise$DefaultPromise#47a86fbb
Yes, but maybe not quite the way you're thinking of. According to the source, only errors that are not NonFatal will escape Future.apply.
try Success(body) catch { case NonFatal(e) => Failure(e) }
i.e. exceptions like: VirtualMachineError, OutOfMemoryError,StackOverflowError, ThreadDeath, LinkageError, InterruptedException, ControlThrowable.. will go uncaught as they represent a fatal JVM error that you will not be able to handle.
A future in itself does nothing except define the computation. It just so happens to be you're using one of the constructors (or apply methods) that, by default, begins running the computation immediately. The mixing of exception handling and concurrency is one of the issues that, unfortunately, not explicit with scala.concurrent.Future. A better alternative may be to use scalaz.concurrent.Task which combines error handling with explicit concurrency.
Why you want to throw an error from your future?
Future is a monad which will handles latency and exceptions while you are dealing with it.
If you look at Future implementation it looks like as below,
trait Future[T] { def onComplete(callback: Try[T] => Unit)(implicit exe..) }
So when as soon as your future gets complete and value available your callback method will be invoked and return unit.
If you see callback method you will get idea your result would be success or error and Try[T] woluld manage all the things for you.