Belvi Nosakhare
Belvi Nosakhare

Reputation: 3255

retryWhen on RxJava with Rx2Apollo

I'm using Rx2Apollo to make a graphql call:

private fun registerCardToken(token: String): io.reactivex.Observable<RegisterCardTokenMutation.RegisterCreditCard> {
    val apolloCall = apolloClient().mutate(RegisterCardTokenMutation.builder().token(token).build())
    return Rx2Apollo.from(apolloCall).map {
        (it.data() as RegisterCardTokenMutation.Data).registerCreditCard()
    }.doOnError({ error ->
        //Log.e("registerCardToke", error.message)
    })


}

This works well, but I want to handle specific error and retry this onces. I have tried to work around this using retryWhen and retry , but not able to write any executable code yet.

The retry persons a token refresh before performing the actual retry. Here's the token refresh sample:

private fun refreshBearerToken(callback: OnCompleteListener<GetTokenResult>) {
        FirebaseAuth.getInstance().currentUser?.getIdToken(true)?.addOnCompleteListener(callback)
    }

Upvotes: 0

Views: 439

Answers (1)

akarnokd
akarnokd

Reputation: 70007

First, you have to turn refreshBearerToken into an Observable

val refreshTokenSource = Observable.create({ emitter ->
    FirebaseAuth.
     getInstance().
     currentUser?.
     getIdToken(true)?.
     addOnCompleteListener({ task -> 
         if (task.isSuccessful()) {
             emitter.onNext(task.getResult())
             emitter.onComplete()
         } else {
             emitter.onError(task.getException())
         }
     }) 
})

Second, use some external reference holding the current token and conditionally use it before calling registerCardToken:

 val currentToken = AtomicReference<String>()

 val registerCardTokenObservable = Observable.defer({
     val token = currentToken.get()
     if (token == null) {
         return refreshTokenSource
            .doOnNext({ currentToken.set(it) })
            .flatMap({ registerCardToken(it) })
     }
     return registerCardToken(token)
 })
 .retry({ error -> 
     if ((error is IOException) || (error.getMessage().contains("network")) {
         currentToken.set(null)
         return true
     }
     return false
 })

Upvotes: 1

Related Questions