I'm using a <long polling> method of retrieving da...
# ktor
m
I'm using a long polling method of retrieving data from the Telegram API and basically, the problem is that it takes sometimes too much time for the client to respond to a response. Basically, I send a request to the server, the server keeps the connection open until some new update arises, and when it does, the server (API) responds to my request, delivering new useful information. Now... It takes sometimes a second (which I consider too much time) from me sending a message until the client registers it. Here's the client code:
Copy code
private val client = HttpClient(CIO) {
    install(DefaultRequest)
    install(ContentNegotiation) {
        json(Config.json)
    }
    install(HttpTimeout) {
        connectTimeoutMillis = 30_000
        requestTimeoutMillis = 30_000
    }
    install(Logging) {
        level = LogLevel.ALL
    }
    defaultRequest {
        url("<https://api.telegram.org/bot${bot.token}/>")
    }
}
And this is how I handle the updates:
Copy code
internal val updateFlow: Flow<Update> = flow {
    while (true) {
        try {
            val updates = getUpdates(
                offset = currentOffset,
                timeout = KramBot.LONG_POLLING_TIMEOUT_SECONDS
            )
            // Telegram servers return an empty JSON array after the timeout if there are no updates
            if (updates.isEmpty()) continue
            updates.forEach { emit(it) }
            currentOffset = updates.last().updateId + 1
        } catch (e: HttpRequestTimeoutException) {
            println("Timed out.")
        }
    }
}

private suspend fun getUpdates(
    offset: Int? = null,
    limit: Int? = null,
    timeout: Int? = null,
    allowedUpdates: List<String>? = null
): List<Update> {
    val response = <http://client.post|client.post>("getUpdates") {
        with(url.parameters) {
            offset?.let { append("offset", it.toString()) }
            limit?.let { append("limit", it.toString()) }
            timeout?.let { append("timeout", it.toString()) }
            allowedUpdates?.let { append("allowed_updates", it.toString()) }
        }
    }
    when (val apiResponse = response.body<ApiResponse<List<UpdateDto>>>()) {
        is ApiResponse.Ok -> return apiResponse.result.map { it.toEntity() }
        is ApiResponse.Error -> error(
            """
                Got an error response from the getUpdates method which should be impossible.
                Error code: ${apiResponse.errorCode}
                Description: ${apiResponse.description}
            """.trimIndent()
        )
    }
}
I made a simplified version and the response is so slow! When I load up the
getUpdates
url in Firefox, it responds immediately to my messages. However, Ktor takes about a second to do so. Why is that?
Copy code
suspend fun main() {
    val offset = "547767852"
    val timeout = "30"
    val address = "<https://api.telegram.org/bot123456789:qwertyuiopasdfghjklzxcvbnm/getUpdates>"
    val client = HttpClient(CIO) {
        install(HttpTimeout) {
            connectTimeoutMillis = 30_000
            requestTimeoutMillis = 30_000
        }
    }

    val response = <http://client.post|client.post>(address) {
        with(url.parameters) {
            append("offset", offset)
            append("timeout", timeout)
        }
    }
    println(response.bodyAsText())
}
a
I’ve measured request time for some clients and here is what I got: Ktor with CIO engine — about 1.5 sec Ktor with Apache engine — about 750 ms Java client — about 450 ms Curl and Insomnia — 100-200 ms
m
Yeah, why is CIO so slow? For me it was the one to rule em all
a
I’ve created an issue to address this problem.
m
Awesome, thank you. How come I'm the first one to notice this? Is this issue only present when contacting Telegram servers?
👆 1
a
Is this issue only present when contacting Telegram servers?
To answer this question deeper investigation is required.
m
Yeah, i hope they'll find out what causes this