Subscriptions in Apollo Kotlin
Subscriptions are long-lived GraphQL read operations that can update their response over time, enabling clients to receive new data as it becomes available.
The GraphQL spec does not specify a particular protocol to use for subscription operations. Apollo Kotlin supports the following protocols:
WebSocket, using one of the following subprotocols:
subscriptions-transport-ws (⚠️ not actively maintained!)
appsync (also uses
graphql-ws
as Sec-WebSocket-Protocol)
HTTP, using chunked multipart responses
You must use whichever transport is supported by your GraphQL endpoint.
You define a subscription in your app just like you define a query, except you use the subscription
keyword. Here's an example subscription for getting the latest value of a number whenever that number is incremented:
1subscription NumberIncremented {
2 numberIncremented
3}
Unlike with queries and mutations, a subscription operation can include only one field of the Subscription
type. To subscribe to multiple fields, you create multiple subscription operations.
Configuring WebSocket subscriptions
By default, Apollo Kotlin uses the
subscriptions-transport-ws
protocol for subscriptions via theSubscriptionWsProtocol
class. This protocol is no longer actively maintained. It remains the default for backward compatibility purposes.A future version of Apollo Kotlin will change the default to the newer
graphql-ws
protocol andGraphQLWsProtocol
class. If your server already usesgraphql-ws
, make sure to set yourWsProtocol
toGraphQLWsProtocol
.
To use subscriptions over WebSocket, use WebSocketNetworkTransport
:
1val apolloClient = ApolloClient.Builder()
2 .subscriptionNetworkTransport(
3 WebSocketNetworkTransport.Builder()
4 .serverUrl("https://apollo-fullstack-tutorial.herokuapp.com/graphql")
5 .build()
6 )
7 .build()
Note: Apollo Kotlin supports both
https://
(orhttp://
) andwss://
(orws://
) protocols. Internally,wss://
is renamed tohttps://
and which one you use does not matter.
Customizing your WebSocket protocol
By default, Apollo Kotlin uses subscriptions-transport-ws for backward compatibility purposes, but it supports all of the following WebSocket subprotocols:
subscriptions-transport-ws (⚠️ not actively maintained!)
appsync (also uses
graphql-ws
as Sec-WebSocket-Protocol)
To customize your protocol, use the WsProtocol
interface. Apollo Kotlin comes with built-in support for the subprotocols above:
Subprotocol | Class |
---|---|
subscriptions-transport-ws | SubscriptionWsProtocol (default) |
graphql-ws | GraphQLWsProtocol |
appsync | AppSyncWsProtocol |
For example, you can configure a graphql-ws
transport like so:
1val apolloClient = ApolloClient.Builder()
2 .subscriptionNetworkTransport(
3 WebSocketNetworkTransport.Builder()
4 .protocol(GraphQLWsProtocol.Factory())
5 .serverUrl("https://apollo-fullstack-tutorial.herokuapp.com/graphql")
6 .build()
7 )
8 .build()
Authentication
Please refer to this section about authentication with WebSocket.
Configuring HTTP subscriptions
To use HTTP for subscriptions, use HttpNetworkTransport
like so:
1val apolloClient = ApolloClient.Builder()
2 .subscriptionNetworkTransport(
3 HttpNetworkTransport.Builder()
4 .serverUrl("https://apollo-fullstack-tutorial.herokuapp.com/graphql")
5 .build()
6 )
7 .build()
This is the only configuration required. HttpNetworkTransport
will use chunked multipart responses for subscription operations and standard POST or GET requests for queries and mutations.
Listening to a subscription
After you configure the NetworkTransport
, use ApolloClient.subscribe
to open the connection and listen for changes:
1apolloClient.subscription(TripsBookedSubscription())
2 .toFlow()
3 .collect {
4 println("trips booked: ${it.data?.tripsBooked}")
5 }
Because subscriptions are long-lasting operations, they return a Flow<Response>
instead of a single Response
.
Terminating a subscription
Termination is handled through the coroutine scope. Cancel the coroutine to terminate the subscription.
By default, a single WebSocket is shared between all active subscriptions. When no subscription is active, the WebSocket is closed after a configurable timeout.
Error handling
Like queries, subscriptions support partial responses with GraphQL errors, which are emitted in the Flow
.
Network errors terminate the Flow
, and you need to retry to get new updates. Depending on the situation, retrying might open a new WebSocket or restart the subscription.
See also this section about WebSocket errors handling.