Race two computations
A number of computations can be raced with each other using the raceSuccess
method, for example:
import ox.{raceSuccess, sleep}
import scala.concurrent.duration.*
def computation1: Int =
sleep(2.seconds)
1
def computation2: Int =
sleep(1.second)
2
val result: Int = raceSuccess(computation1, computation2)
// 2
The losing computation is interrupted. raceSuccess
waits until both branches finish; this also applies to the losing one,
which might take a while to clean up after interruption.
It is also possible to race a sequence of computations, given as Seq[() => T]
.
Race variants
raceSuccess
returns the first success, or if all fail, re-throws the first exceptionraceResult
returns the first success, or if any fail, re-throws the first exception (the first computation which finishes in any way is the “winner”)
Using application errors
Some values might be considered as application errors. If a computation returns such an error, raceSuccess
continues waiting
if there are other computations in progress, same as when an exception is thrown. Ultimately, if no result is successful,
raceSuccess
either throws the first exception, or the first application error that has been reported (whichever comes first).
It’s possible to use an arbitrary error mode by providing it as the initial argument to raceSuccess
.
Alternatively, a built-in version using Either
is available as raceEither
:
import ox.{raceEither, sleep}
import scala.concurrent.duration.*
raceEither({
sleep(200.millis)
Left(-1)
}, {
sleep(500.millis)
Right("ok")
}, {
sleep(1.second)
Right("also ok")
})
Here, the example returns Right("ok")
; the first result is considered an error (a Left
), and the third computation
is cancelled.