Skip to content

Demo repo testing how to use the graphql-redis-subscriptions package, for use in other projects.

Notifications You must be signed in to change notification settings

nsdeschenes/graphql-redis-subscription-demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GraphQL Subscriptions With Redis

This is a simple GraphQL API demo example testing to see the possibility of having a Redis pubsub trigger a GraphQL subscription.

To demo this possibility I am using the graphql-redis-subscriptions pubsub engine. The reason behind using this package rather than creating our own implementation with the apollo-server base PubSub object is detailed here in the apollo-server documents.

For the actual implementation in tracker, I am planning on using a UUID that is added onto the channel as show here, this will give the API the ability to ensure that the user that requested the scan, gets the correct results back. The actual UUID will be randomly generated during the requestScan mutation and sent to the frontend, will be used as an argument in the subscription.

Running the demo

Creating the PubSub, and Client

// index.js
const redis = require('redis')
const { RedisPubSub } = require('graphql-redis-subscriptions')

// ...

const pubsub = new RedisPubSub({
    publisher: redis.createClient(),
    subscriber: redis.createClient()
})

const client = redis.createClient()

client.on("error", function(error) {
    console.error(error);
})

// ...

Server({ pubsub, redis: { redis, client, getAsync, setAsync } }).listen(PORT, (err) => {
    if (err) throw err
})

// ...

In index.js we create the pubsub that we will use in the subscription object type. However to correctly prove that this package is what we are looking for I also pass the redis object into the context for use later on.


Mutation Details

// mutation.js
// ...

resolve: async (_, args, { redis: { redis, setAsync } }) => {
    try {
        await setAsync(args.key, args.value)
    } catch (err) {
        console.error(`Redis Error: ${err}`)
    }

    const publisher = redis.createClient()
    publisher.publish("notification", JSON.stringify({ key: args.key, value: args.value}))
    publisher.quit()

    return 'Sent To Redis'
}

// ...

In mutation.js I create a publisher using the base redis object. The reason I am doing this is to see if the RedisPubSub object properly talks to the Redis cache rather than just using a pubsub.publish() inside the mutation resolver. I initially set the value in the cache so that we can access it later on using queries, then I publish a message on the notification channel with a JSON string, following the publish I close quit the publisher and inform the user that the information has been sent to the cache.


Subscription Details

// subscriptions.js
// ...

const REDIS_PUSHED = 'notification'

// ...

itemPushedToRedis: {
    type: new GraphQLObjectType({
        name: 'RedisPushInfo',
        fields: () => ({
            key: {
                type: GraphQLString,
                resolve: async ({ key }) => {
                    return key
                }
            },
            value: {
                type: GraphQLString,
                resolve: async ({ value }) => {
                    return value
                }
            }
        }),
    }),
    resolve: async (data) => {
        return data
    },
    subscribe: (_, __, { pubsub }) => pubsub.asyncIterator(REDIS_PUSHED)
}

// ...

In subscription.js I define the itemPushedToRedis graphql object inside the subscription graphql object. The key part of this object is the subscribe field at the end of the object. This field returns an AsyncIterator which will listen to the notification channel in the redis cache. When the AsyncIterator is triggered the data that it received is then passed onto the resolver which then in turn resolves the fields in the RedisPushInfo object.


Running this demo

Start Redis Docker Image

docker run -d --network=host --name test-redis redis

Install dependencies

npm install --save

Running the server

npm run start

Demo functions

Ensure that you open different tabs in graphql-playground for each of the following.

Start Subscription

subscription {
  itemPushedToRedis {
    key
    value
  }
}

Execute Mutation

When the mutation is executed you will see the key and value that you submitted as arguments appear in the subscriptions results.

mutation {
  pushToRedis(key: "Key1", value: "First Test Data")
}

Execute Query

When you execute the query, you will retrieve the value from the cache corresponding with the key that you executed the mutation with.

query {
  getFromRedis (key: "Key1")
}

About

Demo repo testing how to use the graphql-redis-subscriptions package, for use in other projects.

Topics

Resources

Stars

Watchers

Forks