Having difficulties with suspendCancellableCorouti...
# coroutines
a
Having difficulties with suspendCancellableCoroutine. Could someone please help me to figure out what I missed? Caused by java.lang.IllegalStateException: Already resumed, but proposed with update kotlin.Unit at kotlinx.coroutines.CancellableContinuationImpl.alreadyResumedError(CancellableContinuationImpl.kt:447) at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:412) at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:388) at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:293) at $wrapStatusListener$$inlined$suspendCancellableCoroutine$lambda$1.onSuccess(Misc.kt:88) at java.lang.reflect.Method.invoke(Method.java) at com.twilio.chat.internal.RethrowingForwarder$RethrowingProxy.invoke(RethrowingForwarder.java:121) at java.lang.reflect.Proxy.invoke(Proxy.java:1006) at $Proxy11.onSuccess() at com.twilio.chat.internal.StatusListenerForwarder$1.run(StatusListenerForwarder.java:33) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7660) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Copy code
suspend fun <T> wrapStatusListener(value: T, block: (StatusListener) -> Unit): T {
    return suspendCancellableCoroutine { continuation: CancellableContinuation<T> ->
        block(object : StatusListener() {
            override fun onSuccess() {
                continuation.resume(value)
            }

            override fun onError(errorInfo: ErrorInfo) {
                continuation.resumeWithException(
                       Exception(
                        code = errorInfo.code,
                        status = errorInfo.status,
                        errorMessage = errorInfo.message
                    )
                )

            }
        })
    }
}
stackoverflow 1
u
Looks like
onSuccess
is called twice by
block
Or
onSuccess
being called after
onError
a
Yes but I don't know what is going here.
u
I would say not coroutines related.
a
Thank you so much for your help
k
it seems like
StatusListener
is a callback which gets invoked more than once. If that’s the case, you’re looking for a
Flow
, not suspend coroutine
👍 1
☝️ 1
a
@kevin.cianfarini Yes, Don't know how to avoid multiple invocation of Listener.
z
Depends on your use case. If this method were named
awaitStatus()
, I would expect it to just wait for the next status update and return it. In that case you could use an AtomicBoolean to ensure that you only invoke resume once. However, if you actually want to be able to return multiple status updates, then your function should return a Flow and probably use the
callbackFlow
builder, as previously suggested.
u
What does
block
return? Is there a way to terminate? I mean you are using
suspendCancellableCoroutine
and not handling cancelation. Maybe this is even the problem. Try to either find a way how to ‘unregister’ your status listener on cancelation or use
suspendCoroutine
. If your can unregister and your issue persists, you should also unregister in
onSuccess
and
onError
to avoid further calls to the listener.
🙏 1
I guess you are wrapping things like this? https://media.twiliocdn.com/sdk/android/chat/releases/0.11.2/docs/com/twilio/chat/ChatClient.html#registerGCMToken-java.l[…]lio.chat.StatusListener- So there is no way to cancel an inflight request. Try using
suspendCoroutine
and please let us know if this solved your issue.
🙇 1
a
@uli Definitely try it, a bit difficult to say it's solve my issue cause it's happening in production but can't reproduce 😕 Thank you all for your help and let you know if I figure out the details.