Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching unhandled errors in Scala futures

If a Scala future fails, and there is no continuation that "observes" that failure (or the only continuations use map/flatMap and don't run in case of failure), then errors go undetected. I would like such errors to be at least logged, so I can find bugs.

I use the term "observed error" because in .Net Tasks there is the chance to catch "unobserved task exceptions", when the Task object is collected by the GC. Similarly, with synchronous methods, uncaught exceptions that terminate the thread can be logged.

In Scala futures, to 'observe' a failure would mean that some continuation or other code reads the Exception stored in the future value before that future is disposed. I'm aware that finalization is not deterministic or reliable, and presumably that's why it's not used to catch unhandled errors, although .Net does succeed in doing this.

Is there a way to achieve this in Scala? If not, how should I organize my code to prevent unhandled error bugs?

Today I have andThen checkResult appended to various futures. But it's hard to know when to use this and when not to: if a library method returns a Future, it shouldn't checkResult and log errors itself, because the library user may handle the failure, so the responsibility falls onto the user. As I edit code I sometimes need to add checks and sometimes to remove them, and such manual management is surely wrong.

like image 514
danarmak Avatar asked Dec 22 '13 12:12

danarmak


People also ask

Is Scala Future blocking?

By default, futures and promises are non-blocking, making use of callbacks instead of typical blocking operations. To simplify the use of callbacks both syntactically and conceptually, Scala provides combinators such as flatMap , foreach , and filter used to compose futures in a non-blocking way.

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.

What is recover in Scala?

Recover requires a partial function which matches an exception and returns the default value. Whereas, recoverWith is used to match an exception and substitute it with another Failure . Using recover to provide a default value.

How do you throw an error in Scala?

The throw keyword in Scala is used to explicitly throw an exception from a method or any block of code.In scala, throw keyword is used to throw exception explicitly and catch it. It can also be used to throw custom exceptions. Exception handling in java and scala are very similar.


2 Answers

I have concluded there is no way to generically notice unhandled errors in Scala futures.

like image 102
danarmak Avatar answered Oct 22 '22 10:10

danarmak


You can just use Future.recover in the function that returns the Future.

So for instance, you could just "log" the error and rethrow the original exception, in the simplest case:

def libraryFunction(): Future[Int] = {
   val f = ...
   f.recover {
      case NonFatal(t) =>
         println("Error : " + t)
         throw t
   }
}

Note the use of NonFatal to match all the exception types it is sensible to catch.
That recover block could equally return an alternative result if you wish.

like image 37
Steve Sowerby Avatar answered Oct 22 '22 08:10

Steve Sowerby