I am working on a decentralized network Android App. There are several servers, I need to find the server that responds the fastest to a network call. It seems easy but surprisingly hard. Any help to solve the issue using Kotlin is appreciated.
There is the current code that Gemini supplied, which unfortunately cannot return@coroutineScope. It is not allowed by the compiler. return@await is allowed, but it does not get out of the coroutineScope, so all the coroutines are waited for. It can cost 10 seconds.
suspend fun getAccessibleIP(ipList: List<String>): String? = coroutineScope {
val deferreds = ipList.filter { isValidPublicIpAddress(it) }.map { ip ->
Timber.tag("getAccessibleIP").d("trying $ip")
async {
try {
HproseInstance.isAccessible(ip)
} catch (e: Exception) {
null
}
}
}
try {
withTimeoutOrNull(2000L) {
select<String?> {
deferreds.forEach { deferred ->
deferred.onAwait { res ->
if (res != null) {
// Cancel remaining deferred values and return the result
deferreds.forEach { it.cancel() }
return@coroutineScope res // Exit coroutineScope and return res
} else {
null
}
}
}
}
}
} finally {
// Ensure all coroutines are cancelled if the function exits
deferreds.forEach { it.cancel() }
}
}
The simplest idiom for this, by a significant margin, is
return channelFlow {
for (ip in ipList) {
if (isValidPublicIpAddress(ip)) {
Timber.tag("getAccessibleIP").d("trying $ip")
launch {
try {
send(HproseInstance.isAccessible(ip))
} catch (e: Exception) {
// do nothing, I guess?
}
}
}
}.firstOrNull()
Using firstOrNull
will cancel all other in-progress work after the first result finishes.