unable to recover in Future - scala - scala

I expect that the following code will generate value 5 as I have written recover to handle the exception and return 5. But I always see the exception in IntelliJ. What is the mistake here?
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success, Try}
import scala.concurrent.duration._
import scala.language.postfixOps
object ConcurrencyExample extends App {
val time = System.currentTimeMillis()
val futures1: Future[Int] = Future {
println("in Future.. sleeping")
Thread.sleep(10)
println("awakein future")
throw new Exception("future failed")
1
}
val result = futures1.map(x=>x+3)
result recover {
case e:Exception => 5
}
result onComplete{
case Success(v)=>println("result is "+v)
case Failure(e) =>println("failed result:"+e)
}
Await.result(result,100 millis)
}
result
in Future.. sleeping
awakein future
Exception in thread "main" LegacyException: future failed

It is not working because the future that would do the recovering is not the one you are calling Await.result() on.
From the Future's scaladoc, we learn that recover creates a new future that will handle any matching throwable that this future might contain. If there is no match, or if this future contains a valid result then the new future will contain the same.
Thus, it is this new future you are now interested in.
Try this:
val result = futures1.map(x=>x+3)
.recover {
case e:Exception => 5
}
Await.result(result,100 millis)

Related

Scala wait for async call to complete in loop

I am new to scala and I have to make an async call ( Elastic indexing using elastic4s ) while iterating through a for each loop. What is the best way to do that in scala.
val data = List("1","2","3","4")
data.foreach(element=>{
asyncCall(element)
})
How to do some action after all the asyncCall is completed. I don'nt want to do anything with the response. Just print success if everything success and print fail if any of the call fails. asyncCall returns Future[T].
You should use Future.sequence. It changes List[Future[T]] to Future[List[T]].
So in your example:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
val f = Future.sequence(data.map(asyncCall)) // Future[List[String]]
//you can now do something when future finishes:
f.onComplete{
case Success(s) => println(s"Evethings fine: $s")
case Failure(e) => println(s"Something went wrong: $e")
}

Scala - How to use a Timer without blocking on Futures with Await.result

I have an Rest API provided by akka-http. In some cases I need to get data from an external database (Apache HBase), and I would like the query to fail if the database takes too long to deliver the data.
One naïve way is to wrap the call inside a Future and then block it with an Await.result with the needed duration.
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
object AsyncTest1 extends App {
val future = Future {
getMyDataFromDB()
}
val myData = Await.result(future, 100.millis)
}
The seems to be inefficient as this implementation needs two threads. Is There an efficient way to do this ?
I have another use case where I want to send multiple queries in parallel and then aggregates the results, with the same delay limitation.
val future1 = Future {
getMyDataFromDB1()
}
val future2 = Future {
getMyDataFromDB2()
}
val foldedFuture = Future.fold(
Seq(future1, future2))(MyAggregatedData)(myAggregateFunction)
)
val myData = Await.result(foldedFuture, 100.millis)
Same question here, what is the most efficient way to implement this ?
Thanks for your help
One solution would be to use Akka's after function which will let you pass a duration, after which the future throws an exception or whatever you want.
Take a look here. It demonstrates how to implement this.
EDIT:
I guess I'll post the code here in case the link gets broken in future:
import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
import akka.actor.ActorSystem
import akka.pattern.after
val system = ActorSystem("theSystem")
lazy val f = future { Thread.sleep(2000); true }
lazy val t = after(duration = 1 second, using = system.scheduler)(Future.failed(new TimeoutException("Future timed out!")))
val fWithTimeout = Future firstCompletedOf Seq(f, t)
fWithTimeout.onComplete {
case Success(x) => println(x)
case Failure(error) => println(error)
}

Exceptions Thrown by Await#result

Given the following code:
import spray.http._
import spray.client.pipelining._
import scala.concurrent.Future
implicit val system = ActorSystem()
import system.dispatcher // execution context for futures
val pipeline: HttpRequest => Future[HttpResponse] = sendReceive
val response: Future[HttpResponse] = pipeline(Get("http://spray.io/"))
The following pseudo-code function waits 10 seconds, returning "GOOD" if the HttpResponse returned, or "BAD" on an Await#result exception (see docs.
import scala.concurrent.Await
import scala.concurrent.duration._
def f(fut: Future[HttpResponse]): String = {
try {
val result = Await.result(fut, 10.seconds)
"GOOD"
}
catch e # (_: InterruptedException | _: IllegalArgumentException
| _: TimeoutException ) => "BAD"
}
In my catch, is it only necessary to catch exception thrown by Await#result? In other words, am I not catching any possible exceptions here?
The Await.result itself can throw the exceptions you caught, however, if the future it awaits does not complete successfully, it forwards the exception contained by the future. You might want to read the Blocking section from here: Futures and Promises.
So yes, there may be exceptions you aren't catching, anything that can result from the failed computation of a HttpResponse.
Blocking in real code is usually bad and should be done only for testing purposes, but if you really need to, I would recommend to wrap the Await in a scala.util.Try so you could manipulate it elegantly later and also keep the information of when and why it failed.

Flaky onSuccess of Future.sequence

I wrote this method:
import scala.concurrent._
import ExecutionContext.Implicits.global
import scala.util.{ Success, Failure }
object FuturesSequence extends App {
val f1 = future {
1
}
val f2 = future {
2
}
val lf = List(f1, f2)
val seq = Future.sequence(lf)
seq.onSuccess {
case l => println(l)
}
}
I was expecting Future.sequence to gather a List[Future] into a Future[List] and then wait for every futures (f1 and f2 in my case) to complete before calling onSuccess on the Future[List] seq in my case.
But after many runs of this code, it prints "List(1, 2)" only once in a while and I can't figure out why it does not work as expected.
Try this for once,
import scala.concurrent._
import java.util.concurrent.Executors
import scala.util.{ Success, Failure }
object FuturesSequence extends App {
implicit val exec = ExecutionContext.fromExecutor(Executors.newCachedThreadPool)
val f1 = future {
1
}
val f2 = future {
2
}
val lf = List(f1, f2)
val seq = Future.sequence(lf)
seq.onSuccess {
case l => println(l)
}
}
This will always print List(1,2). The reason is simple, the exec above is an ExecutionContext of threads (not daemon threads) where as in your example the ExecutionContext was the default one implicitly taken from ExecutionContext.Implicits.global which contains daemon threads.
Hence being daemon, the process doesn't wait for seq future to be completed and terminates. if at all seq does get completed then it prints. But that doesn't happen always
The application is exiting before the future is completes.
You need to block until the future has completed. This can be achieved in a variety of ways, including changing the ExecutionContext, instantiating a new ThreadPool, Thread.sleep etc, or by using methods on scala.concurrent.Await
The simplest way for your code is by using Await.ready. This blocks on a future for a specified amount of time. In the modified code below, the application waits for 5 seconds before exiting.
Note also, the extra import scala.concurrent.duration so we can specify the time to wait.
import scala.concurrent._
import scala.concurrent.duration._
import java.util.concurrent.Executors
import scala.util.{ Success, Failure }
object FuturesSequence extends App {
val f1 = future {
1
}
val f2 = future {
2
}
val lf = List(f1, f2)
val seq = Future.sequence(lf)
seq.onSuccess {
case l => println(l)
}
Await.ready(seq, 5 seconds)
}
By using Await.result instead, you can skip the onSuccess method too, as it will return the resulting list to you.
Example:
val seq: List[Int] = Await.result(Future.sequence(lf), 5 seconds)
println(seq)

Webservice call in Play2 Scala

I want to do something apparently simple: calling a webservice and saving the result in the database.
I'm inside an Akka Actor code and what I do is to call an object method:
object Service {
def run {
val response = WS.url("http://api.server.com/rest/")
.withAuth("test", "test", com.ning.http.client.Realm.AuthScheme.BASIC)
.get.value.get.get.body
}
}
How do I parse the body? I tried to print it on the console but I got NotSuchElement exception.
Any idea, thought? How do I parse arrays, attributes, elements of the XML ?
I'm in the play version 2.1.0
Things have changed a bit since the previous version. Play 2.1.0 depends on the scala.concurrent package instead of their own classes:
A Play Promise is now a Scala Future
A Play Redeemable is now a Scala Promise
I didn't have time to test it, but from the documentation I gathered it should be something like this:
import play.api.libs.ws.WS
import play.api.libs.concurrent.Execution.Implicits._
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.language.postfixOps
object WebserviceCallParseXML {
val responseFuture = WS.url("http://api.server.com/rest/")
.withAuth("test", "test", com.ning.http.client.Realm.AuthScheme.BASIC)
.get()
val resultFuture = responseFuture map { response =>
response.status match {
case 200 => Some(response.xml)
case _ => None
}
}
val result = Await.result(resultFuture, 5 seconds)
println(if (result.isDefined) result.get else "No result found" )
}
The documentation about Future.value:
If the future is not completed the returned value will be None. If the future is completed the value will be Some(Success(t)) if it contains a valid result, or Some(Failure(error)) if it contains an exception.