How We Migrate Android Kitalulus Apollo Client 2.3 to 3.5
At Kitalulus, we mostly use GraphQL as a communication bridge between the client (mobile & web application) and the server. Recently, KitaLulus mobile team worked on migrating our Apollo client from 2.3 to 3.5, and it took a few days to research, debug, monitor, and make sure everything is okay.
Why do we migrate?
Apollo Kotlin 3.0 rewrites most of Apollo Android’s (Version 2. x) internals in Kotlin. Among other improvements, it features:
- Kotlin-first, coroutine-based APIs
- A unified runtime for both JVM and multiplatform
- Declarative cache,
@nonnull
client directives, performance improvements - Proper Caching, at KitaLulus we try to use several caching methodologies like HTTP cache, Automatic Persisted Queries, and Normalized Cache
Migration….
- Execution
We can directly consume the queries as a Coroutine since the newest version is Kotlin-first and it exposes suspend functions by default.
Before
suspend fun regist() { ApolloClient.mutate(
ProfileCreateInput.builder()
.name("Test Name")
.email("test@email.com")
).toDeferred().await()}
After
fun regist() =
ApolloClient.mutation(
ProfileCreateInput(name = "Test Name", email = "test@email.com")
)
2. Meta Data
One of the most noticeable advantages is Kotlin-first, we can directly access metadata from response or define variables more easily
mutation createSomeProfile(
$profileCreateInput : ProfileCreateInput!
){
createProfile(payload: $profileCreateInput){
data
error
isSuccess
warning
}
}
Before migration, when we access/create the metadata, we use the factory builder.
ProfileCreateInput.builder()
.name("Test Name")
.email("test@email.com")
After migration, we use Data Class
directly 🥳
ProfileCreateInput(name = "Test Name", email = "test@email.com")
3. File Upload
There is a significant change if you have upload file features on your GraphQL, you can read details here
Major Issues
We use sentry to monitor KitaLulus Application performance including network performance. When we tried to upgrade the Apollo client, we must upgrade the sentry Apollo client. But we got some problems with this, when we do mutation and the variables have a new line, it will trigger as ApolloHttpException
.
ApolloClient.Builder()
.....
.sentryTracing()
so we must handle Sentry
headers to trim or remove the new line, or just remove the headers from your HTTP request like this
class SentryApolloHeaderInterceptor: ApolloInterceptor {
override fun <D : Operation.Data> intercept(
request: ApolloRequest<D>,
chain: ApolloInterceptorChain
): Flow<ApolloResponse<D>> {
val builder = request.newBuilder()
val modifyHeaders = request.httpHeaders?.filter { item ->
item.name != SentryApollo3HttpInterceptor.SENTRY_APOLLO_3_VARIABLES
}
builder.httpHeaders(modifyHeaders)
return chain.proceed(builder.build())
}
}
Wrap up & References
We are trying to build a better culture every day, and maybe you are the one who is ready to contribute https://bit.ly/joinKLTeam