If I want websocket to not be active when app goes...
# ktor
u
If I want websocket to not be active when app goes to background
Copy code
appInForeground
    .collectLatest { isInForeground ->
        if (isInForeground) {
            val webSocketSession = ktorClient.webSocketSession(..)
            webSocketSession listenAndSend(webSocketSession)
        }
    }
is this enough? or does it need cancelling / closing explicitly? Since the WebSocketSession implements CoroutineScope im not sure
s
I would use the
webSocket
function that takes a callback, and not the one that creates a session explicitly. https://api.ktor.io/ktor-client/ktor-client-core/io.ktor.client.plugins.websocket/[…]ck:%20suspend%20DefaultClientWebSocketSession.()%20-%3E%20Unit) In that case it happens all for you.
Copy code
appInForeground
    .collectLatest { isInForeground ->
        if (isInForeground) {
            ktorClient.webSocket(..) {
              listenAndSend(this)
            }
        }
    }
u
why is that different? isnt the returning variant the same? (just exposing the lambda param as a return value) I thought its just for ergonomics
s
(just exposing the lambda param as a return value) I thought its just for ergonomics
No, because the library wraps your lambda in
try/finally
to close the session which it cannot do when returning the value. Indeed please don't cross post like that. Thank you.
u
I'm looking at the sources and obviously you are right. But, im getting different behavior on the server end (ktor server as well) when client cancels the
connectAndStartListening()
(via collectLatest)
Copy code
private suspend fun connectAndStartListening() {
    ktorClient.webSocket(urlString = wsUrl) {
    	listenAndSend(this)
    }
}

this yields CloseReason(reason=CLOSED_ABNORMALLY, message=Connection was closed without close frame) on server
vs
Copy code
private suspend fun connectAndStartListening() {
    var webSocketSession: DefaultClientWebSocketSession? = null
    try {
        webSocketSession = ktorClient.webSocketSession(urlString = wsUrl)
        listenAndSend(webSocketSession)
    } finally {
        webSocketSession?.close()
        webSocketSession?.incoming?.cancel()
    }
}

this yields CloseReason(reason=NORMAL, message=)
any idea why? or which behavior is more desirable?
I think
close
is not actually called at all (when in the first variant:
webSocket { }
), since the coroutine was cancelled & first suspension point (
close
in finally block) should return right away and do nothing no? but then as im typing this, it makes no sense as the 2nd variant also calls a suspend function in finally block
So, close is entered, but
send(close frame)
throws right aways and flush is never called, so its basically pointless imo; and the CLOSED_ABNORMALLY is called in some other finally unwinding some place else
and btw with okhttp engine the returnless variant gives
CloseReason(reason=INTERNAL_ERROR, message=Client failure)
on cancellation
a
It's better to tell the other end an actual reason for the connection closing, but it depends on the high-level client/server protocol.
u
Agreed, but why do the 2 variants of ktor api behave differently? returnless ws api doesnt send close frame, while the one returning session does sent close frame
👀 1