GraphQL Subscription using Absinthe
Over the last four months, I have been working on a project that helps architects to design strategies they need to optimize workspaces. We have used Elixir, Phoenix, and Absinthe to create a GraphQL API. Currently, we are interacting with this API by sending in queries and mutations. There is a third operation that can be implemented to receive near real-time updates of some server action in the clients of an application.
In this post, I’m going to discuss what GraphQL subscriptions are and how to implement them using Absinthe.
Subscription Operations
Subscription Operations let users submit a GraphQL document that is executed when a specific event happens. Data can then be pushed to users in response to the events through a persistent connection.
For this operation, we use the Publish/Subscribe pattern. By following this pattern, we are able to publish messages that can be consumed by any number of subscribers through a topic.
Setup
In order to create a subscription, we follow these steps:
- Add an Absinthe.Subscription supervisor to the application’s supervision tree. This supervisor starts new processes that will help to broadcast the messages to the subscribers.
- Call use Absinthe.Phoenix.Endpoint to add the additional callbacks in the application endpoint that the macro provides.
- Configure a control channel for handling subscriptions calling use Absinthe.Phoenix.Socket, schema : MyApp.Schema.
- Define a subscription field in your schema.
As you can see in the code, we define a subscription called new_place under the subscription top-level object. Then we use the config macro to define which topic will receive the published messages. In this example, it will be the places-topic.
Once we have completed the previous steps, we are ready to submit new subscriptions.
Executing Subscriptions
The following image shows a submitted subscription that will return the latitude and longitude fields once the server publishes a message to the topic.
To publish a message from the server we can use the Absinthe.Subscription.publish function inside a mutation resolver.
The next code is a mutation resolver that will trigger the new_place subscription using the publish/3 function every time the create place mutation is executed.
The arguments passed to the function are the pubsub module, the value to be broadcast, and the field, along with the topic name that will receive this value.
As can be seen in the image below, the new place data (latitude and longitude) is published once the mutation is executed, then all the clients subscribed to the :new_place field can consume these values through the “places-topic” topic.
Triggers
The trigger macro lets you connect subscription fields to mutations. In certain situations, it is hard to organize all of the sections where events are being published, so it is beneficial to execute a subscription in different mutations.
In the trigger macro above, we have defined the list of mutations that will broadcast data to the topic (or topics) returned by the topic function. For example, we are returning [mutation_option.topic_id] as the list of topics we are going to use for communication.
Resources
You can find more information about this operation at: