is there any good pattern to do the handling of we...
# ktor
b
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
if
scope
is the current scope or a child then it will all work out
b
Ah great…so something like create a child scope and pass that to
WebSocketTransport
?
and have it use that for its
scope.launch
e
yes, that will work, or refactor it to avoid the launch altogether
b
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
so that's one way to do it, although
this@webSocket
should already implement
CoroutineScope
b
Ah! That’s even better
Oh, hm. Using
webSocketSession.launch
doesn’t seem to keep it alive.
e
hmm it doesn't? I'm not sure why that would be… but I guess an explicit
coroutineScope {}
works
b
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
it does create a child scope, it must be something ktor is doing with the pipeline
b
ok
the relevant ktor block is here, i think
so as soon as
handler
finishes, it closes it
r
you can use
client.webSocketSession(request)
if you need manual control over closing
b
@Rustam Siniukov what’s “client” there/what scope is it available in? is that something available inside
routing
?
r
Sorry, my fault. It’s a client API, not server.
a
Maybe, this answer helps you.