This is a rather general question, but hopefully a reasonable one. When is ExecutionContext#reportFailure(Throwable) called?
It doesn't seem to be called in the Scala standard library. I suppose I perhaps should call it in some circumstances? What are these?
This method reports exceptions that cannot be reported otherwise.
It is called when an exception happens during the execution of a callback that has no other way of reporting failure. In particular, calls to Future.onComplete (e.g. via Future.foreach) return Unit and may be executed on any thread, so they have no way of reporting failure back to their callers. When an exception is thrown within onComplete, it is sent to this method.
It is called a couple of times deep within the implementation for Promise in the standard library. See the source.
try onComplete(value) catch { case NonFatal(e) => executor reportFailure e }
An ExecutionContext can implement reportFailure to execute arbitrary code when a future/promise fails. The only thing in the standard library that implements this method is ExecutionContextImpl, which is not in the public API, but found here. This class accepts a reporter: Throwable => Unit function. The default ExecutionContext.Implicits.global uses ExecutionContext.defaultReporter, which simply prints the stack trace to System.err.
If you wanted to customize the behavior, you could need to define your own ExecutionContext. It's difficult to imagine a scenario where you'd want to produce some other side-effect other than logging the stack trace, or some other kind of logging.
Related
I know that I can get hold of the ID of the currently executing fiber by calling
ZIO.descriptor.map(_.id)
However, what I want, is an impure function that I can call from side effecting code, lets define it like
def getCurrentFiberId(): Option[FiberId]
so that
for {
fiberId <- ZIO.descriptor.map(_.id)
maybeId <- UIO(getCurrentFiberId())
} yield maybeId.contains(fiberId)
yields true. Is it possible to define such a function, and if so, how? Note that this question is strongly related to How to access fiber local data from side-effecting code in ZIO.
Not possible. That information is contained in an instance of a class called FiberContext which is practically the core of the ZIO Runtime in charge of interpreting the Effects.
Also, such class is internal implementation and understandably package private.
Additionally there's not only one instance for it, but one for each time you unsafeRun an effect and one more each time a fork is interpreted.
As execution of an effect is not bound to a Thread, ThreadLocal is not used and so, no hope of somehow extracting that info the way you want.
this is a test program:
object Test {
def main(args: Array[String]): Unit = {
// there is an unhandled exception in here, I expect program can remind me, and I can handled it before running.
myException()
}
def myException: Unit ={
throw new Exception
}
}
In Java, when I called a method with unhandling exception, the program will occur error, and tell you add throws declaration or surround with try/catch.
How to know the program have unhandled exceptions before running in Scala?
Scala has a somewhat different philosophy with regards to Exceptions.
The rule of thumb is to not use them unless for something truly exceptional and, thus "let it fail". The reason invoked behind this rule is that, in FP terms, exceptions break referential transparency.
The good practice is to use Either or Option to handle/wrap "errors" rather than throwing exceptions. (the link provided by #Tawkir seems a good read)
Unfortunately this does not help when interfacing with Java code which often uses Exceptions for program control flow, and the compiler will not help you there. A practical way around this is to wrap Exception throwing code with a Try and then call recover or recoverWith to handle these exceptions and, say, wrap them in another structure.
Please note that you can mark a scala method with an #throws annotation to specify the Exception(s) that this method throws, but this should really be used when writing scala code meant to be used by a Java caller expecting an Exception to be thrown.
There's no distinction between checked and unchecked exceptions in the JVM. This is only enforced in the Java compiler, based on whether the class extends RuntimeException or not. Scala compiler doesn't check it, so, there is no way to know, does program have unhandled unchecked exceptions, or not.
Some of my code is async, and I want to test this code's execution has resulted in correct state. I do not have a reference to a Future or a JS Promise that I could map over – the async code in question lives inside a JS library that I'm using, and it just calls setTimeout(setSomeState, 0), which is why my only recourse is to test the state asynchronously, after a short delay (10 ms).
This is my best attempt:
import org.scalatest.{Assertion, AsyncFunSpec, Matchers}
import scala.concurrent.Promise
import scala.scalajs.js
import scala.scalajs.concurrent.JSExecutionContext
class FooSpec extends AsyncFunSpec with Matchers {
implicit override def executionContext = JSExecutionContext.queue
it("async works") {
val promise = Promise[Assertion]()
js.timers.setTimeout(10) {
promise.success {
println("FOO")
assert(true)
}
}
promise.future
}
}
This works when the assertion succeeds – with assert(true). However, when the assertion fails (e.g. if you replace it with assert(false)), the test suite freezes up. sbt just stops printing anything, and hangs indefinitely, the test suite never completes. In case of such failure FooSpec: line does get printed, but not the name of the test ("async works"), nor the "FOO" string.
If I comment out the executionContext line, I get the "Queue is empty while future is not completed, this means you're probably using a wrong ExecutionContext for your task, please double check your Future." error which is explained in detail in one of the links below.
I think these links are relevant to this problem:
https://github.com/scalatest/scalatest/issues/910
https://github.com/scalatest/scalatest/issues/1039
But I couldn't figure out a solution that would work.
Should I be building the Future[Assertion] in a different way, maybe?
I'm not tied to ScalaTest, but judging by the comments in one of the links above it seems that uTest has a similar problem except it tends to ignore the tests instead of stalling the test suite.
I just want to make assertions after a short delay, seems like it should definitely be possible. Any advice on how to accomplish that would be much appreciated.
As was explained to me in this scala.js gitter thread, I'm using Promise.success incorrectly. That method expects a value to complete the promise with, but assert(false) throws an exception, it does not return a value of type Assertion.
Since in my code assert(false) is evaluated before Promise.success is called, the exception is thrown before the promise has a chance to complete. However, the exception is thrown in an synchronous callback to setTimeout, so it is invisible to ScalaTest. ScalaTest is then left waiting for a promise.future that never completes (because the underlying promise never completes).
Basically, my code is equivalent to this:
val promise = Promise[Assertion]()
js.timers.setTimeout(10) {
println("FOO")
val successValue = assert(false) // exception thrown here
promise.success(successValue) // this line does not get executed
}
promise.future
Instead, I should have used Promise.complete which expects a Try. Try.apply accepts an argument in pass-by-name mode, meaning that it will be evaluated only after Try() is called.
So the working code looks like this:
it("async works") {
val promise = Promise[Assertion]()
js.timers.setTimeout(10) {
promise.complete(Try({
println("FOO")
assert(true)
})
})
promise.future
}
The real answer here is: you should try to get the "async" part out of your unit test setup.
All dealing with waits; sleeps; and so on adds a level of complexity that you do not want to have in your unit tests.
As you are not showing the production code you are using I can only make some suggestion how to approach this topic on a general level.
Example: when one builds his threading on top of Java's ExecutorService, you can go for a same-thread executor service; and your unit tests are using a single thread; and many things become much easier.
Long story short: consider looking into that "concept" that gives you "async" in your solution; and if there are ways to avoid the "really async" part; but of course without (!) making test-only changes to your production code.
I'm using the constructor Future.failed to create a failed future, but the failed future still throws the exception when I think it should not.
The method session.loadAll does throw an exception.
I'm also using the Play Framework
It even happens using a try-catch block
I think that Future.failed is not throwing the exception. It looks like it is, because the stack trace is generated at the place where the exception is created.
So, if you use a method like Await.result, or another method that assumes that a future is successful, you will see the exception re-thrown, but the stack trace will make it look as if it was thrown in Future.failed.
First, I'm not quite sure why you're using a future here because these don't look like asynchronous calls.
To answer your question, however, I'm not entirely sure what is going on here, but it looks like you need to be handling the exception. The consumer of the future should use either Future.onComplete and pattern match a Failure type, or Future.onFailure and pattern match on Throwable types.
Scala docs on Future: http://docs.scala-lang.org/overviews/core/futures.html
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.
I have concluded there is no way to generically notice unhandled errors in Scala futures.
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.