https://kotlinlang.org logo
#ktor
Title
# ktor
b

bbaldino

05/03/2022, 10:44 PM
is there any good pattern to do the handling of websocket messages outside the
webSocket
block? I’m trying to do something like:
Copy code
webSocket("/ws") {
    val webSocketTransport = WebSocketTransport(this)
    eventHandler.newWebSocketConnected(webSocketTransport)
}
where the
WebSocketTransport
launches a coroutine to read the incoming messages:
Copy code
scope.launch {
    for (msg in webSocketSession.incoming) {
        ...
    }
}
but when I try this, the websocket disconnects immediately, because it looks like it’s implemented in a way to close as soon as the passed
handler
returns. Is there any good pattern move that logic out? I did it one way where I added another channel, and the webSocket handler read messages and wrote them to that channel, and WebSocketTransport read from that channel, but was hoping to avoid having to create the intermediary.
e

ephemient

05/03/2022, 10:49 PM
if
scope
is the current scope or a child then it will all work out
b

bbaldino

05/03/2022, 10:52 PM
Ah great…so something like create a child scope and pass that to
WebSocketTransport
?
and have it use that for its
scope.launch
e

ephemient

05/03/2022, 10:53 PM
yes, that will work, or refactor it to avoid the launch altogether
b

bbaldino

05/03/2022, 10:56 PM
I now have:
Copy code
webSocket("/ws") {
            coroutineScope {
                val webSocketTransport = WebSocketTransport(this@webSocket, this@coroutineScope)
                handler.newWebSocketConnection(sessionId, webSocketTransport)
            }
        }
which seems to be working right…does that look reasonable?
the
scope.launch
is done in the
WebSocketTransport.init
, so it kicks that off before
coroutineScope
closes, which I’m assuming is required to keep the parent webSocket scope “alive”
e

ephemient

05/03/2022, 10:59 PM
so that's one way to do it, although
this@webSocket
should already implement
CoroutineScope
b

bbaldino

05/03/2022, 11:00 PM
Ah! That’s even better
Oh, hm. Using
webSocketSession.launch
doesn’t seem to keep it alive.
e

ephemient

05/03/2022, 11:01 PM
hmm it doesn't? I'm not sure why that would be… but I guess an explicit
coroutineScope {}
works
b

bbaldino

05/03/2022, 11:03 PM
from what i can tell it doesn’t. i can stick with the coroutineScope method…bit uglier but it seems to work.
perhaps because
launch
alone doesn’t create a child scope? (does it?)
e

ephemient

05/03/2022, 11:04 PM
it does create a child scope, it must be something ktor is doing with the pipeline
b

bbaldino

05/03/2022, 11:04 PM
ok
the relevant ktor block is here, i think
so as soon as
handler
finishes, it closes it
r

Rustam Siniukov

05/04/2022, 9:30 AM
you can use
client.webSocketSession(request)
if you need manual control over closing
b

bbaldino

05/04/2022, 3:32 PM
@Rustam Siniukov what’s “client” there/what scope is it available in? is that something available inside
routing
?
r

Rustam Siniukov

05/05/2022, 6:53 AM
Sorry, my fault. It’s a client API, not server.
a

Aleksei Tirman [JB]

05/08/2022, 3:32 PM
Maybe, this answer helps you.
2 Views