Jeff
05/12/2021, 6:58 PMsourceA().handleErrorWith {
sourceB().handleErrorWith {
sourceC()
}
}Joram Visser
05/12/2021, 7:10 PMsourceA()
.flatMap { sourceB() }
.flatMap { sourceC() }
If you only want to invoke sourceB and sourceC in cases errors occurred, then I guess your approach is fine.Jeff
05/12/2021, 8:05 PMJoram Visser
05/12/2021, 8:30 PMJoram Visser
05/12/2021, 8:32 PMJeff
05/13/2021, 3:12 AMfirstRight(a(), b(), c()).fold(onA, onB, onC)
Which wouldn’t cancel on a Left but would cancel on a Right and would return that Right.Joram Visser
05/13/2021, 6:44 AMsimon.vergauwen
05/13/2021, 8:20 AMswap on Either which swaps the side so you could do.
race({ eitherA().swap() }, { eitherB().swap() }).swap()
It's a bit tedious but for sure the easiest way to achieve your tasks without to much overhead since 3x swap is minimal compared to dispatching 3 times. (2 for launching tasks, and one again to return to original ctx).simon.vergauwen
05/13/2021, 8:21 AMhandleErrorWith is the correct way of chaining Left you can consider it flatMapLeft and thus you could also write a eitherLeft { } block for it if you'd want to.Joram Visser
05/13/2021, 8:37 AMsimon.vergauwen
05/13/2021, 8:41 AMJoram Visser
05/13/2021, 8:46 AMkeepRetryingSourceAUntilItYieldsARight(maxRetries)Joram Visser
05/13/2021, 8:47 AMJoram Visser
05/13/2021, 8:48 AMsimon.vergauwen
05/13/2021, 8:55 AMLeft.
This is a snippet I whipped together and should be thoroughly tested but basically, it just keeps track of how many task have finished and the first Left it encounters.
If all task run out without a Right winning the race than the first encountered Left will be returned rather than the last which marked the race as finsihed with all Left.
The first Right wins the race.
This is achieved by making Left suspend and thus not allowing them to complete the race
suspend fun <E, A> firstRight(fa: suspend () -> Either<E, A>, fb: suspend () -> Either<E, A>): Either<E, A> {
var firstLeft: Atomic<Either<E, A>?> = Atomic(null)
var finished: Atomic = Atomic(0)
suspend fun Either<E, A>.suspendOnLeft(): Either<E, A> =
when(this) {
is Right -> this
is Left -> when {
finished.get() == 2 -> firstLeft.get()!!
else -> {
firstLeft.update { current -> if(current == null) this else current }
finished.update(Int:inc)
suspendCoroutine<A> { }
}
}
return race({ fa().suspendOnLeft() }, { fb().suspendOnLeft() }) }
}simon.vergauwen
05/13/2021, 8:56 AMif(firstLeft.get() != null) finished.update(Int::inc) else firstLeft.update { this }
This line needs to be rewritten to use modify on Atomic instead since this is not atomically soundsimon.vergauwen
05/13/2021, 9:02 AMsimon.vergauwen
05/13/2021, 9:04 AMsuspend and Either is an important focus of Arrow