How the retry should be implemented?

Hi,

I am bit lost what are the ways to implement retry logic.

I have a simple code like this

 val response = runBlocking {
        val mutation = apolloClient.mutation(
          UpdateCollectionMainStageMutation(
            input = it.first,
            version = version,
            metadata = Optional.present(it.second)
          )
        )
        mutation.execute()
      }

I see the there were some suggestions from old github comments, but not sure if they are accurate.

I see in the doc for react Retry Link - Apollo GraphQL Docs , is there something for Kotlin?

Hi!

If you only need to retry certain operations on a case-by-case basis, you can simply enclose the call to execute into a try catch block and treat the exception here. Also check response.errors for GraphQL errors. It could be an extension on ApolloClient to be nicer to use, something like:

suspend fun <T : Query.Data> ApolloClient.tryQuery(query: Query<T>, retryCount: Int): T? {
    for (i in 0..retryCount) {
        val response = try {
            this.query(query).execute()
        } catch (e: Exception) {
            // Log the errors
            continue
        }
        if (response.hasErrors()) {
            // Log the errors
            continue
        }
        return response.data
    }
    return null
}

If you want to have this behavior for all operations, you can use an ApolloInterceptor for this, which will be automatically be called for all operations. Something like this:

class RetryInterceptor(private val retryCount: Long) : ApolloInterceptor {
    override fun <D : Operation.Data> intercept(
        request: ApolloRequest<D>,
        chain: ApolloInterceptorChain
    ): Flow<ApolloResponse<D>> {
        return chain.proceed(request)
            .onEach { response ->
                if (response.hasErrors()) {
                    throw Exception("There were GraphQL errors")
                }
            }
            .retry(retryCount) { true }
    }
}

and use it on your client like this:

    val apolloClient = ApolloClient.Builder()
        .serverUrl("https://...")
        .addInterceptor(RetryInterceptor(3))
        .build()