Hello, I’m making network client with Apollo in Kotlin Multiplatform. My purpose is to handle errors logic in one place for both platforms (IOS + Android)
I’m trying to handle token expiration case: getting some kind of error from server, making mutation for prolongation and updating token locally. I am concerned about the situation when other requests with the old token may come in parallel during the prolongation, since the new one has not yet been received. Is there a way out of the box to make operations await for token prolongation operation == make them consistent (may be some kind of queue)? Or may be interceptors should solve my problem?
Hi!
Maybe you can be inspired by this Interceptor?
As you can see you could use a kotlinx.coroutines.sync.Mutex
to ensure no parallel operations will happen while a token is being refreshed.
If your token refresh is done via a GraphQL mutation, then you will need a way to bypass this interceptor for this particular mutation - this could be done by passing a specific header to this mutation, and in the interceptor, call chain.proceed
right away if it’s present.
Oh, I saw this interceptor but I thought it wouldn’t be enough. Thank you for your idea, I’ll try to dive deeper into this kind of solution
Hello, if I understand correctly, then the GraphQL concept does not involve the use of http statuses. As I understand it, all responses come in status 200, at least using python + fast api + ariadne/graphene. Thus, determining the error status becomes problematic.
Are there any other possible ways other than to parse the HttpResponse for the presence of a GraphqlError of the appropriate type, which seems inappropriate in the Interceptor, while the interceptor itself seems to be a pretty convenient place to pause all requests and make everything consistent.
Hi!
If the token expiration error is surfaced at the GraphQL level then you could use an ApolloInterceptor
.
-
HttpInterceptor
: interceptor at the HTTP level -
ApolloInterceptor
: interceptor at the GraphQL level
Okay, thank you, I will look for ApolloInterceptor
Hi, I looked more closely in ApolloInterceptor. It allows to override method:
override fun <D : Data> intercept(
request: ApolloRequest<D>,
chain: ApolloInterceptorChain
): Flow<ApolloResponse<D>>
which is not suspend. So I am not able to get result from chain.proceed() because it returns flow which requires coroutine context to collect it and read errors from response. Why is intercept not suspend like in HttpInterceptor? I suppose that it is not possible to check for GraphQL errors inside this kind of interceptor
Hi! By coincidence, somebody had a very similar question recently, and in the ticket you can see an outline of how to use ApolloInterceptor
for this use case.
Don’t hesitate to tell us if you need more guidance!
Thank you very much, that seems to solve my problem. I will try