Hey guys, trying to basic async endpoint with `kto...
# ktor
s
Hey guys, trying to basic async endpoint with `ktor`:
Copy code
override val route: Routing.() -> Unit
        get() = {
            get("healthz") {
                val dbState = asyncGetDatabaseState()

                var res = HealthModel(
                        status = Server.status,
                        database = dbState.await(),
                        redis = RedisHealth("null", 0)
                )

                call.respond(res)
            }
        }

    suspend fun getDatabaseState(): DatabaseHealth {
        delay(500) //sleep for 500ms

        return DatabaseHealth(
                host = Config.config[DatabaseConfig.host],
                database = Config.config[DatabaseConfig.database],
                latencyMs = 500
        )
    }

    fun asyncGetDatabaseState() = async {
        getDatabaseState()
    }
But I keep getting
Caused by: io.ktor.server.engine.BaseApplicationResponse$ResponseAlreadySentException: Response has already been sent
even though actual content is sent back to client with HTTP 200. What am I doing wrong?
o
Do you mean that
HealthModel
is being correctly sent, and then something else is attempting to send another respond? We would need more information to help…
s
HealthModel
is being correctly sent but in the log I can see the exception. I don't think there's something else trying to respond
it seems like
BaseApplicationResponse
is intercepting the call after it was responded:
Copy code
Caused by: io.ktor.server.engine.BaseApplicationResponse$ResponseAlreadySentException: Response has already been sent
	at io.ktor.server.engine.BaseApplicationResponse$$special$$inlined$apply$lambda$1.doResume(BaseApplicationResponse.kt:30)
@orangy FYI. Changing backend from
netty
to
jetty
helped. It seems like with
netty
even this https://github.com/ktorio/ktor/tree/master/ktor-samples/ktor-samples-async is logging the same exception I had
o
Will check it. What version are you using?
s
0.9.0
o
Try latest alpha, please
s
same with
0.9.1-alpha-8
. I'll try to run the sample but at least my code works ok with jetty and throws exception with netty
sample works ok with
netty
. now I'm completely out of ideas what's wrong about my code
o
I might need more code to see what’s going on or even debug…
s
@orangy I simplified snippet to this:
Copy code
suspend fun testSuspend(): Int {
    delay(500)

    val random = java.util.Random()
    return random.nextInt(100)
}

fun main(args : Array<String>) {
    embeddedServer(Netty, 9000) {
        install(Routing) {
            get("/healthz") {
                val start = System.currentTimeMillis()

                val calcResult = async { testSuspend() }.await()

                val end = System.currentTimeMillis()

                call.respond("Runtime ${end - start}ms Result ${calcResult}")
            }
        }
    }.start(wait = true)
}
o
Thanks! Will try to repro and report back
s
call.respondText
works ok though
o
I cannot reproduce it on master. However I’ve found a different problem (and fixed). We are going to release a build tomorrow, so let’s wait till then and try on your side, it might already be fixed.
👍 1
n
isn't this the same as the issue I've logged some time ago? https://github.com/ktorio/ktor/issues/268
o
No, it isn’t. See example above, there are no second handler.
Second handler warning is still on my list (soon)
@Sergey Chikin 0.9.1-alpha-9 has been published, please try it with your case
s
@orangy same here. it's quite interesting that changing
call.respond
to
call.respondText
is resolving this problem. but in my case I need it to responding with JSON so need
call.respond(Any)
o
Weird. Your sample works fine for me. You said you need JSON, do you install ContentNegotiation with JSON?
s
Yep
o
But does simplified snipped you posted works for you now? I can’t reproduce the problem and don’t understand what can go wrong… One guess I have is an exception is thrown that is not tracked/reported, and that causes 500 Internal Server Error to be attempted.
s
Hm
Sec
Cannot find local variable: name = this
I guess I'm doing something wrong
o
Nope, it’s debugger issues…
Huh, I don’t know…
s
I'll setup a gradle project for the whole case
o
Thanks a lot! I hope that’s not something specific to your OS setup or something…
s
I have macOS High Sierra
o
I will check it tomorrow. I have macOS High Sierra too.
I have no exceptions when I run the project and open
<http://localhost:9000/healthz>
in browser