Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get hold of exceptions thrown in a Scala Future?

I've been working up my answer to Is there a standard Scala function for running a block with a timeout?, and have run into a problem if an exception is thrown in a Future.

  def runWithTimeout[T](timeoutMs: Long)(f: => T) : Option[T] = {
    awaitAll(timeoutMs, future(f)).head.asInstanceOf[Option[T]]
  }

So that

runWithTimeout(50) { "result" } should equal (Some("result"))
runWithTimeout(50) { Thread.sleep(100); "result" } should equal (None)

But if I throw an exception in my block it doesn't leak, but is swallowed - so that the following fails with "..no exception was thrown"

intercept[Exception] {
    runWithTimeout(50) { throw new Exception("deliberate") }
}.getMessage should equal("deliberate")

Syserr has a stack trace with the message

<function0>: caught java.lang.Exception: deliberate

but I can't find where in the Scala runtime that is printed.

Apart from wrapping f in another block which catches exceptions and propagates them if thrown, is there any way to persuade awaitAll and/or Future to throw?

like image 227
Duncan McGregor Avatar asked Jun 03 '11 16:06

Duncan McGregor


People also ask

How do you handle exceptions in Scala?

try/catch/finally A basic way we can handle exceptions in Scala is the try/catch/finally construct, really similar to the Java one. In the following example, to make testing easier, we'll return a different negative error code for each exception caught: def tryCatch(a: Int, b: Int): Int = { try { return Calculator.

How do you handle Future Scala?

Whenever we create a new Future operation, Scala spawns a new thread to run that Future's code, and after completion it executes any provided callbacks. Scala will infer that add has a return type of Future[Int] , and the enclosed code will execute in its own thread when the function is called.

Does Scala have onComplete blocking?

onComplete() we are no longer blocking for the result from the Future but instead we will receive a callback for either a Success or a Failure. As such, we've also had to import scala. util.

How does Future work in Scala?

Future represents a result of an asynchronous computation that may or may not be available yet. When we create a new Future, Scala spawns a new thread and executes its code. Once the execution is finished, the result of the computation (value or exception) will be assigned to the Future.


1 Answers

Short answer: no.

Exceptions don't do what you want when you're working in a threaded context, because you want to know about the exception in the caller, and the exception happens in the future's thread.

Instead, if you want to know what the exception was, you should return an Either[Exception,WhatYouWant]--of course, you have to catch that exception within the future and package it up.

scala> scala.actors.Futures.future{
  try { Right("fail".toInt) } catch { case e: Exception => Left(e) }
}
res0: scala.actors.Future[Product with Serializable with Either[Exception,Int]] = <function0>

scala> res0()   // Apply the future
res1: Product with Serializable with Either[Exception,Int] =
      Left(java.lang.NumberFormatException: For input string: "fail")
like image 171
Rex Kerr Avatar answered Oct 14 '22 05:10

Rex Kerr