Working with GraphQL subscriptions
API Connect for GraphQL allows you to set up GraphQL subscriptions for every data source.
In addition to queries and mutations, GraphQL also offers subscriptions as an operation type. Subscriptions allow a GraphQL API to push updates to a client in real-time rather than requiring the client to poll the server for new data.
API Connect for GraphQL watches for changes
in your data source and pushes them to your GraphQL API. Subscriptions support the graphql-transport-ws subprotocol as exemplified by the npm
package graphql-ws
.
Implementing subscriptions
A typical implementation is GraphQL query polling, which periodically runs a GraphQL query and returns a new subscription result whenever the result of the subscription changes. You can do this with API Connect for GraphQL quickly and without additional infrastructure. You'll also have to trade off the overhead of regular polling and the possible lag in noticing a change. API Connect for GraphQL will execute queries on behalf of a subscription with a reduced cache TTL (time to live).
Polling queries
A subscription field provides a @materializer
GraphQL query for polling queries.
This query is resolved using the same endpoint, and if the data changes, it is returned to the
subscription channel.
In the following example, we'll use a simple random number generator. The field
Query.random
will return a random number between 0 and 999999, generated by a
JavaScript function defined in the ecmascript
option of the @rest
directive.
type Random {
number: Int
}
type Query {
random: Random
@rest(
endpoint: "stepzen:empty"
ecmascript: """
function transformREST(s) {
return ({
number: Math.floor(Math.random() * 999999)
});
}
"""
)
}
You can add a subscription field that polls Query.random
as follows:
type Subscription {
random: Random @materializer(query: "random")
}
Test this subscription with the following CLI command:
stepzen request 'subscription { random { number}}'
The response looks like the following example:
Subscribed to ws://localhost:9000/stepzen-subscriptions/YOUR_ENDPOINT/__graphql
event #1 (+1.5s)
1 | {
1 | "data": {
1 | "random": {
1 | "number": 468435
1 | }
1 | }
1 | }
event #2 (+9.4s)
2 | {
2 | "data": {
2 | "random": {
2 | "number": 754591
2 | }
2 | }
2 | }
This example does not demonstrate the filtering that happens on subscriptions. Suppose our
example can also return random strings. In that case, after the subscription selection is evaluated,
subscription { random { number string } }
, then the resulting selection is checked
for differences against the prior result. If there is a difference, the new value is pushed to the
client.
To obtain consistent results, the API Connect for GraphQL server might reduce caching when executing subscription queries, so your backend services might see an increase in queries.
Using subscriptions
GraphQL APIs are implemented over HTTP -- except for subscriptions, which are implemented over
WebSockets. To invoke a subscription, you must use a client that supports
graphql-transport-ws
; for example the stepzen request
command
provided by the API Connect for GraphQL CLI.
You can use subscriptions with the CLI, or with a JavaScript client as explained in the sections that follow.
Using subscriptions with the CLI
With the API Connect for GraphQL CLI, you can
use the stepzen request
command to execute a subscription. The stepzen
request
command opens a WebSocket connection to the API Connect for GraphQL server, executes the
subscription, and then displays the results of the subscription as they are received.
To use the stepzen request
command, you'll need a API Connect for GraphQL workspace in the current
directory. You can then use the stepzen request
command to execute a subscription.
For example, to execute the subscription subscription { random { number}}
, run the
following command:
stepzen request 'subscription { random { number}}'
See API Connect for GraphQL CLI for more
information about the stepzen request
command.
Using subscriptions with the JavaScript client
You can also use subscriptions directly from a JavaScript application, preferably using the
library graphql-ws
. This library uses a sub- protocol of WebSockets known as
graphql-transport-ws
(not to be confused with the deprecated library
graphql-transport-ws
from Apollo).
Authorization information (like your API Connect for GraphQL API key) is specified in
graphql-ws
as connectionParams
.
You can find a complete example of using API Connect for GraphQL subscriptions with
graphql-ws
in the examples.
Subscriptions and URIs
The URIs for subscriptions include a wss
code for secure WebSockets prefix (or
ws
for local docker), and prefix the path with
stepzen-subscriptions
as shown in Table 1.
endpoint URL | endpoint subscription URI |
---|---|
http://localhost:9000/YOUR_ENDPOINT/__graphql
|
ws://localhost:9000/stepzen-subscriptions/YOUR_ENDPOINT/__graphql
|
https://ACCOUNT.stepzen.net/YOUR_ENDPOINT/__graphql
|
wss://ACCOUNT.stepzen.net/stepzen-subscriptions/YOUR_ENDPOINT/__graphql
|
Replace YOUR_ENDPOINT
with the name of your endpoint and
YOUR_ENDPOINT
with your API Connect for GraphQL domain. When you deploy your
endpoint to API Connect for GraphQL, the
subscriptions URI is displayed so you can note it down.