Skip to content

android: Disabled background data causes errors #8188

Open
@jchau207

Description

@jchau207

Hello, we have an app, that implements a widget that gets data using a GRPC stream on an update. However we have many instances where the widget fails to update where we are receiving:

io.grpc.StatusRuntimeException: UNAVAILABLE: Keepalive failed. The connection is likely gone
        at io.grpc.Status.asRuntimeException(Status.java:533)
        at io.grpc.stub.ClientCalls$BlockingResponseStream.hasNext(ClientCalls.java:629)
        at kotlin.sequences.SequencesKt___SequencesKt.toCollection(_Sequences.kt:722)
        at kotlin.sequences.SequencesKt___SequencesKt.toMutableList(_Sequences.kt:752)
        at kotlin.sequences.SequencesKt___SequencesKt.toList(_Sequences.kt:743)

we are building our channel with the following parameters:

            AndroidChannelBuilder.forAddress("<backend-url-->", 443)
                .context(context)
                .keepAliveWithoutCalls(true)
                .keepAliveTime(5, TimeUnit.SECONDS)
                .keepAliveTimeout(5, TimeUnit.SECONDS)
                .useTransportSecurity()
                .intercept(MetadataInterceptor())
                .build()

and we care calling our stream collection using:

        clientWalletCall =
            channel.newCall(ChartsServiceGrpc.getGetWalletLiveChartMethod(), service.callOptions)

I am assuming, when the app goes the background (due to the user's OS setting restricting background data) that the main grpc channel gets broken and needs time to restart, so when the widget wakes up to update, the call fails.

What is the best way to address this issue where we need block till the channel is ready to ensure the stream is successful?

Activity

sanjaypujare

sanjaypujare commented on May 19, 2021

@sanjaypujare
Contributor

Take a look at https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md and you want to wait until the channel is READY. You can use ManagedChannel.getState() to get the current state of the channel and use ManagedChannel.notifyWhenStateChanged() to be notified when the channel is READY to achieve your blocking.

jchau207

jchau207 commented on May 20, 2021

@jchau207
Author

Is this similar to withWaitForReady? How long does withWaitForReady blocked for and does it respect withDeadline as well?

sanjaypujare

sanjaypujare commented on May 20, 2021

@sanjaypujare
Contributor

Is this similar to withWaitForReady? How long does withWaitForReady blocked for and does it respect withDeadline as well?

Yes, you can use withWaitForReady. The semantics are described in https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md

ejona86

ejona86 commented on May 26, 2021

@ejona86
Member
dapengzhang0

dapengzhang0 commented on May 26, 2021

@dapengzhang0
Member

withWaitForReady should work if the call is started after the wakeup.

If a call was started and received part of the response just milliseconds before the app goes to the background, I'm not sure what Android would do then, but if you see "UNAVAILABLE: Keepalive failed. The connection is likely gone" after the wakeup, then unfortunately there is nothing grpc library can do.

jchau207

jchau207 commented on May 26, 2021

@jchau207
Author

Thank you for the response, If the call goes: "UNAVAILABLE: Keepalive failed. The connection is likely gone" what exactly is the connection state? From observation, the channel does eventually fix it self so I should expect withWaitForReady work for the scenario.

From our experience using GRPC in app development, we find that many users restrict background data usage on their phone and the GRPC channel kinda goes berserk when the app is in the background ping ponging between Transient Failures and Connecting. Are there any plans to allow the channel be more application life cycle aware and park channel state in a state that is quicker or reliable to reconnect after wake up?

ejona86

ejona86 commented on Aug 2, 2021

@ejona86
Member

If the call goes: "UNAVAILABLE: Keepalive failed. The connection is likely gone" what exactly is the connection state?

At the time of the RPC it was READY, but it transitioned to TRANSIENT_FAILURE.

Are there any plans to allow the channel be more application life cycle aware and park channel state in a state that is quicker or reliable to reconnect after wake up?

I think the most appropriate thing to do here is channel.enterIdle() which will drop the connection. If there's an existing RPC though, there may be something better depending on if the network is already cut off. It isn't clear to me what the appropriate notifications to listen for are. I see Activity.onUserLeaveHint() may be relevant, but it'd take some more digging to see if there's not other things that are more appropriate.

changed the title [-]Android widget updates with GRPC[/-] [+]android: Disabled background data causes errors[/+] on Aug 2, 2021
added this to the Next milestone on Aug 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @ejona86@dapengzhang0@temawi@sanjaypujare@jchau207

      Issue actions

        android: Disabled background data causes errors · Issue #8188 · grpc/grpc-java