Hello colleagues! I’ve just found that implementat...
# arrow
g
Hello colleagues! I’ve just found that implementations of
raceN()
probably not handling exceptions in a right way. According to the conversation I had a year ago, it seems to me that if one of functions will throw an exception, then another will not be cancelled. Do you have an idea how to check such behaviour?
s
Hey @genovich, That is the idea behind the
raceN
operator. I just read your conversation with Roman, and the canceling is happening after
select
. https://github.com/arrow-kt/arrow/blob/225e16f4f22e9458c1d8fe96ae5aa8242306fe17/ar[…]x-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Race2.kt Here you can see that if
Left
wins, then it cancels
Right
.
probably not handling exceptions in a right way.
Oh, exceptions. So if
fa
fails that it cancels
fb
? There is indeed test missing for that 🤔 We should definitely write them! They can be written in a similar fashion than the other tests I linked. If you do write them, please raise a PR for this 🙏
g
Sure, thank you
s
I just wrote a quick test to see if it works as expected, and this passes.
Copy code
val latch = CompletableDeferred<Unit>()
val exitCase = CompletableDeferred<ExitCase>()
val res = Either.catch {
    raceN(
        {
            guaranteeCase({
                latch.complete(Unit)
                awaitCancellation()
            }) { require(exitCase.complete(it)) }
        },
        {
            latch.await()
            throw RuntimeException("")
        }
    )
}
require(res is Either.Left)
require(exitCase.await() is ExitCase.Cancelled)
Is that the behavior you expect?
So
fa
got canceled due to
fb
throwing an exception, and the result of
raceN
is the exception thrown by
fb
.
g
Yes, I thought that
fa
will not be cancelled when
fb
will throw an exception.
Looks like this was an issue for earlier versions of
select
Or I just don't understand something about how
coroutineScope
works inside
Anyway, thank you for checking, glad to know that everything is working
🙌 1
s
Arrow builds this around
select
. I don't think
select
cancels the other one out of the box. There are some gotchas
CoroutineScope
, and depending on the actual implementation of the
CoroutineScope
can also behave differently. That's why we prefer higher-level operators as we define in Arrow, then you can ignore these lower-level things.
g
Oh, I meant
coroutineScope()
function. I read it’s documentation and it says that all coroutines will be cancelled if one of them throw an exception