Redis-graphql-subscription and NodeJs Tutorial

900x500

1, Why do we need redis-graphql-subscription ? Redis-graphql-subscription is a library implement redis associate with graphql-subscription. This package implements the PubSubEngine Interface from the graphql-subscriptions package and also the new AsyncIterator interface. It allows you to connect your subscriptions manager to a Redis Pub Sub mechanism to support multiple subscription manager instances. Let’s look at a GraphQL subscription request:

subscription monkeysLocation($limit: Int!) { flyingMonkeysMoved($limit) {
location {
lat
lon
height
}
movementVector } } This request contains three parts:

Subscription operation name — this can be anything you like, and is mostly helpful for debugging:

subscription monkeysLocation($limit: Int!) { The root subscription field and parameters, often used for filtering publications:

flyingMonkeysMoved(limit: $limit) { The GraphQL selection set, which specifies which fields we want to get in the result: location {
lat
lon
height
}
movementVector All of this allows the client to get exactly the data that it needs.

That last part of the query is the actual difference between GraphQL subscriptions and the “regular” Pub Sub paradigm. This is also the part of GraphQL subscriptions that can easily become a bottleneck if you don’t pay attention, because GraphQL resolvers can run any async or sync job that you would like them to.

Future Optimizations Right now the Subscriptions Manager runs the GraphQL query for each event and each subscriber. A pretty simple PR could implement shared execution for subscribers with the same query — as long as the response is not user-specific.

The Apollo team is also getting ready to implement GraphQL subscriptions in some of their own production apps, which will provide some more on-the-ground information about the performance of the system.

2, Compare between graphql-subscription libraries GraphQL subscriptions is a simple npm package that lets you wire up GraphQL with a pubsub system (like Redis) to implement subscriptions in GraphQL. There are many pubsub implementation library

PubSub Implementations It can be easily replaced with some other implementations of PubSubEngine interface. There are a couple of them out there:

Use Redis with https://github.com/davidyaha/graphql-redis-subscriptions Use Google PubSub with https://github.com/axelspringer/graphql-google-pubsub Use MQTT enabled broker with https://github.com/davidyaha/graphql-mqtt-subscriptions Use RabbitMQ with https://github.com/cdmbase/graphql-rabbitmq-subscriptions Use Kafka with https://github.com/ancashoria/graphql-kafka-subscriptions Use Postgres with https://github.com/GraphQLCollege/graphql-postgres-subscriptions Use NATS with https://github.com/moonwalker/graphql-nats-subscriptions Use multiple backends with https://github.com/jcoreio/graphql-multiplex-subscriptions From top to bottom , we can easily see that redis and google pubsub implementation is the first 2 options you should consider first The number of community support of these two are quite large. If you get trouble, they can help you You can consider to choose the implementation which is suitable for you own server, database 3, Basic setup STEP 0: Download and install redis-server on your local machine

Follow the link to https://redis.io/download to download the suitable version for your OS

After installing redis, you can test it with a few steps

Start the redis server by navigate to your redis directory by command line

cd ~/redis-5.x.x src/redis-server Secondly, You can interact with Redis using the built-in client:

src/redis-cli then let’s try with “ping” , the output should be “pong”

With very basic usage, you can interact with redis database by using these command

$ src/redis-cli redis> set foo bar OK redis> get foo "bar" STEP 1 install graphql-redis-subscription for your project

Follow the link https://github.com/davidyaha/graphql-redis-subscriptions

Make sure you have already installed NodeJs and NPM on your local machine

Install redis-subscriptions by using npm

Install redis-subscriptions by using npm As a peer-dependencies, graphql-subscription must be installed too

npm install graphql-subscriptions In this tutorial we used one more thing to easily setup the redis with NodeJs. Go to https://github.com/luin/ioredis and install ioredis. The setup is quite simple that you can follow the documentation. Including it to this article may be too long and unnecessary.

STEP 2 Using redis graphql subscriptions on your project by adding this code

import * as Redis from 'ioredis';

const options = { host: REDIS_DOMAIN_NAME, port: PORT_NUMBER, retry_strategy: options => { // reconnect after return Math.max(options.attempt * 100, 3000); } };

const pubsub = new RedisPubSub({ ..., publisher: new Redis(options), subscriber: new Redis(options) }); If you didn’t pass the options to Redis, it will automatically set the host to http://localhost and the port to 6379

STEP 3: Run your subscription and check the terminal

In the command line, enter

redis-cli monitorOK Your output subscription should arrive here whenever you publish a subscription

Below is simple graphql subscription example Define your GraphQL schema with a Subscription type:

schema { query: Query mutation: Mutation subscription: Subscription }

type Subscription { somethingChanged: Result }

type Result { id: String } Now, let's create a simple RedisPubSub instance:

import { RedisPubSub } from 'graphql-redis-subscriptions'; const pubsub = new RedisPubSub(); const SOMETHING_CHANGED_TOPIC = 'something_changed';

export const resolvers = { Subscription: { somethingChanged: { subscribe: () => pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC), }, }, } Subscriptions resolvers are not a function, but an object with subscribe method, that returns AsyncIterable.

Calling the method asyncIterator of the RedisPubSub instance will send redis a SUBSCRIBE message to the topic provided and will return an AsyncIterator binded to the RedisPubSub instance and listens to any event published on that topic. Now, the GraphQL engine knows that somethingChanged is a subscription, and every time we will use pubsub.publish over this topic, the RedisPubSub will PUBLISH the event over redis to all other subscribed instances and those in their turn will emit the event to GraphQL using the next callback given by the GraphQL engine.

pubsub.publish(SOMETHINGCHANGED_TOPIC, { somethingChanged: { id: "123" }}); Dynamically create a topic based on subscription args passed on the query: export const resolvers = { Subscription: { somethingChanged: { subscribe: (, args) => pubsub.asyncIterator(${SOMETHING_CHANGED_TOPIC}.${args.relevantId}), }, }, } Using both arguments and payload to filter events import { withFilter } from 'graphql-subscriptions';

export const resolvers = { Subscription: { somethingChanged: { subscribe: withFilter( (_, args) => pubsub.asyncIterator(${SOMETHING_CHANGED_TOPIC}.${args.relevantId}), (payload, variables) => payload.somethingChanged.id === variables.relevantId, ), }, }, } References We are done now, let's try to publish a subscription and check your command line with redis-cll monitor. If you subscription came, Congratulation !!!

In the next part, we will walk through graphql-google-subscription This article was written by @Harry and reference to these following:

https://blog.apollographql.com/graphql-subscriptions-with-redis-pub-sub-f636fc84a0c4

https://github.com/davidyaha/graphql-redis-subscriptions

https://redis.io/

Thanks for reading !