Conversation
|
Made test out of this example, but it seems like its green. Could there be something wrong with how I made the test? |
| object AsyncFatalError extends IOApp { | ||
| def run(args: List[String]): IO[ExitCode] = { | ||
| IO.async_[Unit](cb => cb(Left(new OutOfMemoryError("Boom!")))) | ||
| .flatMap(_ => IO.println("sadness")) |
There was a problem hiding this comment.
The original reproducer in #4505 runs the async on a fiber and joins it:
_ <- pingFiber.join
} yield ExitCode.Successjoin returns an object with the outcome of the fiber. This ignores the actual outcome of the async call. Your implementation doesn't use a fiber, so the failure is still propagated and causes your IO to fail. pingFiber also fails, the issue is it doesn't fatally fail.
The core issue with #4505 is that the code shouldn't even get far enough that there is a join result, as the OOM should kill the app immediately. You can probably reproduce this with just an attempt instead of a start/join
| .flatMap(_ => IO.println("sadness")) | |
| .attempt | |
| .flatMap(_ => IO.println("sadness")) |
or to more closely replicate the original, something like:
| .flatMap(_ => IO.println("sadness")) | |
| .start | |
| .flatMap(_.join) | |
| .flatMap(_ => IO.println("sadness")) |
There was a problem hiding this comment.
Applied the second change here, it made the test red: ec8421b
Thanks!
448a5dd to
31ea3e2
Compare
|
@reardonj I made the test red and added turned them green. Added separate test for the completable future case and it seems to be working as well. Does this look like the right approach? |
reardonj
left a comment
There was a problem hiding this comment.
This solution makes sense to me, though I'm not especially familiar with Cont implementation details. @durban did note that there are some edge cases:
A tricky thing with cont is that the callback might be called with something which might not be used. (Multiple results, and also cont can complete synchronously.)
I think one of these would be eg. the fiber is canceled then the callback is invoked. I don't know how we would handle that offhand since the fiber might already be complete. Hopefully a maintainer can help a bit there. This looks like it covers the normal flows though!
| CompletableFuture.runAsync( | ||
| () => { | ||
| println("Waiting 2 seconds before boom...") | ||
| Thread.sleep(2000) |
There was a problem hiding this comment.
Is there a reason to sleep?
There was a problem hiding this comment.
I just copied the example verbatim from the original ticket, the wait is there: #4505
Fixes #4505.
AsyncFatalErrorIOFiber.runLooprun loop for caseIOCont, before continuing run loopIOFiber.asyncContinueFailedRfor asynchronous continuation