Scala Future not printing results - scala

I am learning Scala Future with the following code:
object DangerousAndSlowService {
def queryNextNumber: Long = {
50
}
}
val number1F = Future { DangerousAndSlowService.queryNextNumber }
number1F.onComplete({
case Success(value) => {
println(s"Got the callback, meaning = $value")
}
case Failure(exception) => {
exception.printStackTrace
}
})
However, the "50" is never printed.
Already spent several hours but still cannot figure it out.
Thanks.

The main thread exits without letting the future finish its job, therefore the output is non-deterministic: sometimes it does print something, sometimes it doesn't. If you don't mind blocking the main thread, you can use Await:
import scala.concurrent.Future
import scala.util.{Success, Failure}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._
object DangerousAndSlowService {
def queryNextNumber: Long = {
50
}
}
val number1F = Future { DangerousAndSlowService.queryNextNumber }
number1F.onComplete({
case Success(value) => {
println(s"Got the callback, meaning = $value")
}
case Failure(exception) => {
exception.printStackTrace
}
})
Await.result(number1F, 1.second)
While Await is necessary here to produce the output, it's also good to note you should use it with caution. It blocks the current thread, which is typically not what you want when you work with asynchronous computations and futures.

Related

how to do non blocking wait on a future for 10 seconds?

import scala.concurrent.{Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
import scala.util.Random
object Example1 extends App {
println("starting calculation ...")
val f = Future {
sleep(Random.nextInt(500))
42
}
println("before onComplete")
f.onComplete {
case Success(value) => println(s"Got the callback, meaning = $value")
case Failure(e) => e.printStackTrace
}
sleep(2000)
}
Using Await.ready we can wait for 10 seconds and if the future is not completed it throws a TimeoutException. But Await.ready is blocking. What is the best way to wait for 10 seconds when using callback like in the above example ?(without using frameworks like Akka)
It is hard to believe, but scala standard library does not include this functionality :(
There are alternative Future implementations that do - like com.twitter.util.Future or scalaz.concurrent.Future, but with the standard scala Future you cannot get it out of the box.
You can implement it yourself, but that looks kinda ugly :(
object FutureCancellator {
val scheduler = ??? // You can use whatever scheduler available within your system - like akka scheduler or whatever, or roll your own, based on a timer thread.
class Within[T](val f: Future[T]) extends AnyVal {
def within(d: Duration): Future[T] = {
val timeout: Future[T] = scheduler.after(d) { _ =>
throw new TimeoutException(e)
}
Future.firstCompletedOf(f, timeout)
}
}
}
Now, you can do things like:
import FutureCancellator._
import scala.concurrent.duration._
someFuture
.within(10 seconds)
.onComplete {
case Success(foo) => println(s"got $foo")
case Failure(t: TimeoutException) => println("timeout")
case Failure(e) => e.printStackTrace
}

How to avoid try with Future fromTry

I need to write a future that flushes a stream and closes it. Here is what I tried:
def close(ous: OutputStream) = Future.fromTry(Try {
try {
ous.flush()
} finally {
ous.close()
}
})
Looks ugly. try{}finally{} inside the Try. But I need finally block in order to avoid resource leak. Is there a way to rewrite the code in not so ugly way?
Future already captures exceptions returning a Future.failed, there's no need to do fromTry and block, so you can do:
Future { out.flush() }.andThen( _=> out.close )
( Future { out.flush() } will asynchronously flush the stream and andThen will get called wether it finishes or fails.
This could be an option i think.
def close(ous: OutputStream) = Future.fromTry(Try(ous.flush())) andThen {
case Success(_) => println("do something here")
case Failure(_) => ous.close()
}
It's not clear to me whether this is actually cleaner:
def close(ous: OutputStream) = Future.fromTry(
val flushed = Try { ous.flush() }
val closed = Try { ous.close() }
if (closed.isFailure) closed else flushed // bubble up the correct error
)
Note: This is nearly an equivalent of this answer but not quite. Mainly since the .close can fail, and this must be encapsulated in the Try.
since you are already using Try use pattern match on result to Try{ stream.flush } and apply Try{ stream.close() }
example,
import java.io.{ByteArrayOutputStream, OutputStream}
import java.util.Date
import java.io.ObjectOutputStream
import scala.concurrent.Future
import scala.util.Try
import scala.util.{Failure, Success}
import scala.concurrent.ExecutionContext.Implicits.global
def doSomeOperation: OutputStream => Future[String] = (outputStream: OutputStream) =>
withCleanup(outputStream) {
Future {
//1/0
outputStream.toString
}
}
def withCleanup(outputStream: OutputStream)(fn: Future[String]): Future[String] = {
val execution = fn
execution onComplete {
case Success(_) => cleanup(outputStream)
case Failure(_) => cleanup(outputStream)
}
execution
}
def cleanup(outputStream: OutputStream): Try[Unit] = Try {
outputStream.flush()
println("flushed")
} match {
case _ => Try {
outputStream.close()
println("closed")
}
}
Then call the function, which will flush and close your stream as well.
val stream = new ObjectOutputStream(new ByteArrayOutputStream())
stream.writeObject(new Date())
scala> doSomeOperation(stream)
res18: scala.concurrent.Future[String] = Future(<not completed>)
flushed
closed

How do I test scala.js programs for side-effects that happen asynchronously using µtest?

I have a µtest suite that needs to check that some asynchronous operation eventually has a side effect. Since javascript (and thus scala.js) is single threadded, it is not possible to block and wait for the side effect to happen. Also, the µtest eventually method does not work on javascript runtime. How do I perform such a test?
If you return a Future from a µtest, then the test will pass if the future succeeds and fail if the future fails. Thus, you can schedule the conditional check for some point in the future without blocking.
I wrote a simple eventually method that accomplishes this:
package utest
import rx.ops.DomScheduler
import scala.concurrent.{Promise, Future}
import scala.concurrent.duration.FiniteDuration
import scala.util.{Failure, Success, Try}
object JsOps {
import scala.concurrent.ExecutionContext.Implicits.global
val scheduler = new DomScheduler
def eventually(eval: => Try[Boolean])(implicit timeout: FiniteDuration): Future[Boolean] = {
val p = Promise[Boolean]()
scheduler.scheduleOnce(timeout) {
eval match {
case Success(b) => p.success(b)
case Failure(t) => p.failure(t)
}
}
p.future
}
}
Here is an example of usage:
import scala.concurrent.duration._
implicit val timeout = 30.milliseconds
eventually {
if (/*condition holds true*/) {
Success(true)
} else Failure(new RuntimeException(/*error message*/))
}

Why does my simple scala object hangs for a minute or so while it includes a future

I am learning scala futures and I hit my question already. I have a very simple example
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util.{Failure, Success}
/**
* Created by dummy on 05/02/15.
*/
object FutureUtils extends App{
val f = Future {
Thread.sleep(1000)
println("I am learning scala futures")
"learning"
}
f onComplete {
case Success(value:String) => println("got the response back")
case Failure(t: Throwable) => println("did not expect this")
}
println("I am still learning")
}
When I run the program as-is output never prints
got the response back
instead looks like it hangs for a minute or so and ends without printing the expected output ever. I am sure I am missing something very basic here.
I also tried adding System.in.read() at the end and it seems when I input any dummy value, programs ends printing expected result. What is the reason behind this behavior? Could anyone please help me understand this?
The reason the program doesn't work without the System.in.read() is that onComplete does not block until the future completes but merely adds a callback for when it does. That callback never gets executed because the whole program ends before the future completes. To fix this problem, you could deliberately let the main thread go into an infinite loop and explicitly terminate the process in the callback.
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util.{Failure, Success}
object Main extends App {
val f = Future {
Thread.sleep(1000)
println("I am learning scala futures")
"learning"
}
f onComplete {
case Success(value:String) => println("got the response back"); System.exit(0)
case Failure(t: Throwable) => println("did not expect this"); System.exit(1)
}
println("I am still learning")
while (true){
Thread.sleep(1000)
}
}
You need to await the future, the program is exiting before it completes.
import scala.concurrent.Await
import scala.concurrent.duration._
var myFuture = Future {
Thread.sleep(1000)
1
}
// oncomplete handlers, etc here
println(Await.result(myFuture, 5 seconds))
EDIT: If you must use onComplete and can't verify that those handlers are executed before Await.ready/result then you should use formal synchronization, i.e.:
import scala.concurrent._
import java.util.concurrent.CountDownLatch
object Main extends App {
val f = Future {
Main.synchronized {
Thread.sleep(1000);
1
}
}
val latch = new CountDownLatch(1)
f.onComplete {
case _ => { latch.countDown() }
}
latch.await()
}
Well... since you are sleeping for 1000 miliseconds inside your future, your future will take at least 1 second to complete. The app thread completes itself and exits in this time.
You have to make sure that the app thread is alive when the future completes. You can do this by sleeping in your app thread for some time... like this.
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util.{Failure, Success}
object FutureUtils extends App{
val f = Future {
Thread.sleep(1000)
println("I am learning scala futures")
"learning"
}
f onComplete {
case Success(value:String) => println("got the response back")
case Failure(t: Throwable) => println("did not expect this")
}
// Wait for some time
// Not sure future will complete in this time or not
Thread.sleep(1000);
Thread.sleep(1000);
Thread.sleep(1000);
}
But, the better way to do this is by making it so that the app thread needs the future to complete.
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util.{ Failure, Success }
object FutureUtils extends App {
val f = Future {
Thread.sleep( 1000 )
println( "I am learning scala futures" )
"learning"
}
f onComplete {
case Success( value:String ) => println( "got the response back" )
case Failure( t: Throwable ) => println( "did not expect this" )
}
while ( f.value == None ) {
// Waste time just till the future is complete.
}
// Do something with future value.
f.foreach( ( s: String ) => println( s ) )
}

Why does Future's recover not catch exceptions?

I'm using Scala, Play Framework 2.1.x, and reactivemongo driver.
I have an api call :
def getStuff(userId: String) = Action(implicit request => {
Async {
UserDao().getStuffOf(userId = userId).toList() map {
stuffLst => Ok(stuffLst)
}
}
})
It works fine 99% of the time but it may fail sometimes (doesn't matter why, that's not the issue).
I wanted to recover in a case of an error so i added:
recover { case _ => BadRequest("")}
But this does not recover me from errors.
I tried the same concept on the scala console and it worked:
import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
var f = future { throw new Exception("") } map {_ => 2} recover { case _ => 1}
Await.result(f, 1 nanos)
This returns 1 as expected.
I currently wrapped the Async with:
try{
Async {...}
} catch {
case _ => BadRequest("")
}
And this catches the errors.
I went over some Scala's Future docs on the net and I'm baffled why recover did not work for me.
Does anyone know why? What do I miss to sort it out?
Why it fails actually matters 100%. If we spread the code over a number of lines of code, you'll understand why:
def getStuff(userId: String) = Action(implicit request => {
Async {
val future = UserDao().getStuffOf(userId = userId).toList()
val mappedFuture = future.map {
stuffLst => Ok(stuffLst)
}
mappedFuture.recover { case _ => BadRequest("")}
}
})
So, UserDao().getStuffOf(userId = userId).toList() returns you a future. A future represents something that may not have happened yet. If that thing throws an exception, you can handle that exception in recover. However, in your case, the error is happening before the future is even being created, the UserDao().getStuffOf(userId = userId).toList() call is throwing an exception, not returning a future. So the call to recover the future will never be executed. It's equivalent to doing this in the Scala repl:
import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
var f = { throw new Exception(""); future { "foo" } map {_ => 2} recover { case _ => 1} }
Await.result(f, 1 nanos) }
Obviously that doesn't work, since you never created the future in the first place beacuse the exception was thrown before the code to create the future happened.
So the solution is to either wrap your call to UserDao().getStuffOf(userId = userId).toList() in a try catch block, or find out why it's failing in whatever method you're calling, and catch the exception there, and return a failed future.
If you have a later version of Play eg 2.2.x, you can do this:
def urlTest() = Action.async {
val holder: WSRequestHolder = WS.url("www.idontexist.io")
holder.get.map {
response =>
println("Yay, I worked")
Ok
}.recover {
case _ =>
Log.error("Oops, not gonna happen")
InternalServerError("Failure")
}
}