detouched
10/13/2017, 5:09 AMselect
that waits for the first successful result (opposed to the existing one that waits for the first completed clause, no matter exceptionally or not).
First of all, am I reinventing the wheel? If not, here's what I ended up with – does it make sense? Any issues you can see here?
private suspend fun <R, D : Deferred<R>> selectFirstSuccessful(deferredList: List<D>,
failedDeferredList: List<D>): Triple<R?, List<D>, List<D>> =
if (deferredList.isEmpty()) {
Triple(null, deferredList, failedDeferredList)
} else {
try {
select<Triple<R?, List<D>, List<D>>> {
deferredList.forEach { deferred ->
deferred.onAwait { result -> Triple(result, deferredList - deferred, failedDeferredList) }
}
}
} catch (e: Exception) {
val completedExceptionally = deferredList.filter { it.isCompletedExceptionally }
val notCompletedExceptionally = deferredList - completedExceptionally
selectFirstSuccessful(notCompletedExceptionally, completedExceptionally + failedDeferredList)
}
}
Full code with usage example is here: https://gist.github.com/detouched/73f366cb730ece629b9141dea96d3a98voddan
10/13/2017, 6:03 PM