Looking into using Ktor Server for websockets. Whi...
# ktor
t
Looking into using Ktor Server for websockets. While playing around with them I was testing how the coroutine scope works. WebSocketSession implements CoroutineScope so I assumed calling
close
on the websocket would cancel the coroutine scope and clean up children jobs. This doesn't seem to be the case, which I can work around, but I was wondering if this is the behavior for a specific reason?
a
Could you please share a code snippet to illustrate your issue?
t
Good idea. This is based upon the websocket sample, but simplified to show the point:
Copy code
webSocket("/ws") { // websocketSession
    println("started")
    outgoing.send(Frame.Text("Hello Friend!"))

    launch {
        try {
            awaitCancellation()
        } catch (_: Exception) {
            println("complete")
        }
    }
    close(CloseReason(CloseReason.Codes.NORMAL, "Client said BYE"))
}
In this situation I would expect that upon calling close that the launched block would be cancelled and complete is printing. Similarly, it appears that if close isn't called here and instead the client disconnects the launch block is also NOT canceled
c
I’m wondering if it’s actually that
launch
is never actually started because you aren’t reading from the websocket. The whole scope is canceled before
launch
is actually dispatched, and therefore never actually enters the
launch
block. Since you’re not reading from
incoming
, I think it would just immedately return from
websocket { }
, thus cancelling the
coroutineScope
instead of suspending Have you tried putting a
println()
inside
launch
before
try
to see if it even gets started? If you change it to
launch(start = CoroutineStart.UNDISPATCHED) { }
do you see the same thing?
t
Yes it does get started. And if I explicitly call cancel() after close it prints "complete"
Copy code
routing {
    webSocket("/ws") { // websocketSession
        println("started")
        outgoing.send(Frame.Text("Hello Friend!"))

        launch {
            try {
                println("entered")
                awaitCancellation()
            } catch (_: Exception) {
                println("complete")
            }
        }
        close(CloseReason(CloseReason.Codes.NORMAL, "Client said BYE"))
        cancel()
}