Hello! We are encountering connection issues with ...
# apollo-kotlin
m
Hello! We are encountering connection issues with subscriptions under low internet and fluctuating network conditions. Scenarios: 1. Low Internet: The WebSocket continuously attempts to connect, getting stuck without timing out. No exceptions are thrown, making it difficult to handle the issue properly. 2. No Internet: The subscription results in an SSLHandshakeException, which is expected. [Just stating the no internet case] 3. Connection Loss Post-Establishment: After successfully establishing the WebSocket connection, if the internet connection is lost, the WebSocket becomes stuck in a "Receiving response body" status. Despite no keep-alive messages being sent, it doesn't time out as per set idleTimeoutMillis, and no exceptions are thrown to handle the situation properly. We have even added retry mechanisms, which do not seem to help in above cases Could someone please help here?
Copy code
val client = ApolloClient.Builder()
         client.networkTransport(
            HttpNetworkTransport.Builder()
                .serverUrl(serverUrl = endpoint)
                .httpEngine(gqlEngine(buildType))
                .build(),
        )

client.subscriptionNetworkTransport(
    WebSocketNetworkTransport.Builder()
        .idleTimeoutMillis(20000L)
        .protocol(
            SubscriptionWsProtocol.Factory(connectionPayload = {
                mapOf(
                    "x-token" to "",
                    "Authorization" to ""
                )
            })
        )
        .serverUrl(serverUrl = endpoint)
        .addHeaders(
            listOf(
                HttpHeader("Accept", "application/json"),
                HttpHeader("Content-Type", "application/json"),
                HttpHeader("Connection", "keep-alive, Upgrade"),
                HttpHeader("Upgrade", "websocket"),
                HttpHeader("x-token", "")
            )
        )
        .reopenWhen { _, attempt ->
            if (attempt >= 3L) {
                false
            } else {
                delay(attempt * 1000L) // Exponential backoff (1s, 2s, 4s)
                true
            }
        }
        .build()
)
Copy code
public fun <D : Subscription.Data, T> ApolloClient?.subscribe(
    subscription: Subscription<D>,
    mapper: suspend (data: D?) -> Either<FelixError, T>
): Flow<T> = channelFlow {
    try {
        this
           .subscription(subscription)
           .toFlow()
           .retryWhen { cause, attempt ->
                if (cause is ApolloNetworkException && attempt < 1) {
                    delay(attempt * 1000L) // Exponential backoff
                    true
                } else {
                    false
                }
            }
            .map {
               mapper(it.data)
            }
            .catch { e ->
                 send(
                    // send exception
                )
            }.collectLatest {
                send(it)
            }
    } catch (e: Exception) {
        send(
            // send exception
        )
    }
}
m
Hey 👋 Indeed, that’s an area that’s historically been quite hard to debug/make very reliable. May I suggest trying version 4? Not only it has new WebSockets APIs but it also contains network awareness
It’s also reaching release candidate really soon
m
Hi, we are unable to update to version 4 as it is still in the release candidate stage, which is not permitted by our company policies. Could you please help us identify the issue with the existing code?
m
Hi 👋 It’s really hard to tell without more information about your environment. At a high level, I would try to simplify your current code.
reopenWhen {}
is the one you want to use for connectivity issues, I’m not sure about the
channelFlow {}
and
retryWhen {}
in the
subscribe
call. Can you reproduce consistently? If you can reproduce the issue with the tutorial, that would help a ton. There’s a subscription where you can trigger events by running this mutation and it will display a toast.
On a separate note, we just released 4.0.0-rc.1 so it’s a matter of days/weeks before it goes stable.
👍 1
🎉 1