Hi everyone, I'm facing an issue with Ktor in KMP ...
# ktor
a
Hi everyone, I'm facing an issue with Ktor in KMP (Kotlin Multiplatform) on Android/JS. The problem is that the second
async
branch of the following code doesn't get executed:
Copy code
override suspend fun loadBalances(assets: List<...>): List<...> = coroutineScope {
    awaitAll(
        async { loadA(assets) },
        async { loadB(assets) },
    ).flatten()
}
However, when I use the following code with
delay()
functions, it works as expected, which indicates that the issue might not be with the coroutines setup:
Copy code
override suspend fun load(assets: List<...>): List<...> = coroutineScope {
    awaitAll(
        async {
            delay(200)
            listOf(...)
        },
        async {
            delay(500)
            listOf(...)
        },
    ).flatten()
}
Additionally, the problematic code works fine in an Android project with okHttp. I suspect the issue might be related to dispatchers, but I'm not sure where to make adjustments. Any advice or guidance on this issue would be greatly appreciated!
a
Can you share a complete code snippet?
a
which part, are you looking for? on Android it just being called in Activity:
Copy code
lifecycleScope.launch {
            val balances = loadBalances()
            val tvLog = findViewById<TextView>(R.id.tv_log)
            tvLog.text = balances
        }
for JS it's wrapped into the promise:
Copy code
private fun <T> exportPromise(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T,
): Promise<T> =
    GlobalScope.promise(context, start, block)
        .catch { throw it.toJsRpcError() }
j
What are
loadA
and
loadB
? Are those suspend functions?
The problem is that the second
async
branch of the following code doesn't get executed
Does the first one complete? Does it succeed? Fail?
In which dispatcher are you calling
loadBalances()
? You said it works on Android, what is the caller in the case where it doesn't work?
a
Hey @Joffrey 1.
loadA
and
loadB
are both POST calls. 2. The first function
loadA
is fully complete,
loadB
runs and stops once it reaches the Ktor POST call 3. They don't use any custom Dispatchers. 4. This code doesn't work on Android and JS 5. This code is working on a different Android project with okHttp, TBH it's unrelated to this.
this is the setup of ktor on Android side:
Copy code
HttpClientEngineFactory<OkHttpConfig> {
    private const val MAX_IDLE_CONNECTIONS = 20
    private const val IDLE_TIMEOUT = 5L
    private val connectionPool = ConnectionPool(MAX_IDLE_CONNECTIONS, IDLE_TIMEOUT, TimeUnit.SECONDS)
    private val dispatcher = Dispatcher()

    override fun create(block: OkHttpConfig.() -> Unit): HttpClientEngine {
        val defaultHttpConfig = OkHttpConfig().apply {
            config {
                connectionPool(connectionPool)
                dispatcher(dispatcher)
            }
        }

        return OkHttpEngine(defaultHttpConfig.apply(block))
    }
}