Building Real time API using graphql subscriptions easily

In this article, we will see how to build a real time api using graphQL Subscriptions. Building Real time API using graphql subscriptions easily.

If you are new to GraphQL, read this article to get the concepts of GraphQL before reading further.

We all know that web sockets are the important concepts nowadays which is widely used in many real time applications. Using that,we can able to build a real time API's.

But wait, we have been using web sockets with REST API design. how can we use it in the GraphQL.

There's comes the concept of GraphQL Subscriptions. GraphQL subscriptions is used to build a real time communication in the application.

Why we need that?

we can still use web sockets connections in web applications. the problem with web sockets (As far as i know and faced in production) is, it is hard to maintain when it scales. you have to open a socket in your front end and backend of your applications.

Also, you have to close it properly to avoid the load in server. there are few cases like this.

On the other hand, GraphQL is completely abstacted one where developer can easily manage the subscription. it will take care of all the technical difficulties.

It is similar to how you define and use Queries and Mutations in GraphQL.

Okay..Enough of this theory. it's time to implement in a Nodejs Application.

Implementing Subscription in Nodejs Application

Let' see how to implement GraphQL Subscription in Node.js. I Assume that you have some experience in using babel setup in node.js application.

If not, you can read this article to get good grasp of it. we are going to implement a simple api to understand the concept of GraphQL subscriptions.

GraphQL Subscriptions Logical WorkFlow

graphql subscriptions

Firslty, setup the express graphql boilerplate referring this article. create app.js and add the following code

1import express from "express"
2import bodyParser from "body-parser"
3import { ApolloServer, gql } from "apollo-server-express"
4import { merge } from "lodash"
5import { createServer } from "http"
6import cors from "cors"
7const app = express()
8
9app.use(cors())
10app.use(bodyParser.json())
11app.use(bodyParser.urlencoded({ extended: false }))
12
13require("dotenv").config()
14
15const schema = gql``
16
17const resolvers = {
18 Query: {},
19 Mutation: {},
20 Subscription: {},
21}
22
23const server = new ApolloServer({
24 typeDefs: schema,
25 resolvers: resolvers,
26 playground: {
27 settings: {
28 "editor.theme": "dark",
29 },
30 },
31 context: {
32 async({ req, connection }) {
33 if (connection) {
34 return connection.context
35 } else {
36 return req
37 }
38 },
39 },
40})
41
42server.applyMiddleware({ app, path: "/graphql" })
43
44const httpServer = createServer(app)
45server.installSubscriptionHandlers(httpServer)
46
47httpServer.listen(3005, () => {
48 console.log(`Server is running on PORT 3005`)
49})

Here, we have the basic set to run the GraphQL Express application. Let's create a db connection and import it inside our app.js

1const mongoose = require("mongoose")
2
3class DB {
4 constructor() {
5 this._db = null
6 this.URL = process.env.MONGODB_URL
7 }
8}
9
10DB.prototype.initDB = function() {
11 mongoose
12 .connect(this.URL, { useNewUrlParser: true })
13 .then(db => {
14 this._db = db
15
16 console.log(`DB is connected successfully`)
17 return this._db
18 })
19 .catch(err => {
20 throw new Error(err)
21 })
22}
23
24DB.prototype.getDB = function() {
25 if (this._db) {
26 return this._db
27 } else {
28 return this.initDB()
29 }
30}
31
32module.exports = DB

add the _db.js file inside the app.js

1import DB from "./_db"
2
3const _db = new DB()
4_db.getDB()

After that, create a model file called postModel.js to use it inside the GraphQL resolver.

1import Mongoose from "mongoose"
2
3const postSchema = new Mongoose.Schema({
4 title: {
5 type: String,
6 },
7 body: {
8 type: String,
9 },
10 createdUserId: {
11 type: String,
12 },
13})
14
15class Post {
16 static getPostById(id) {
17 return this.findOne({
18 _id: id,
19 }).exec()
20 }
21
22 static insertPost(postInfo) {
23 const post = this(postInfo)
24
25 return post.save()
26 }
27}
28
29postSchema.loadClass(Post)
30
31export default Mongoose.model("Post", postSchema)

Let's create an Mutation to create a post. create a directory called postResolvers and add createPost.js file in it.

1import PostModel from "../postModel"
2export default async (parent, args, context) => {
3 try {
4 let postInfo = {
5 title: args.request.title,
6 body: args.request.body,
7 createdUserId: args.request.createdUserId,
8 }
9 const postCollection = await PostModel.insertPost(postInfo)
10
11 return {
12 success: true,
13 data: postCollection,
14 error: null,
15 }
16 } catch (e) {
17 return {
18 success: false,
19 data: null,
20 error: {
21 status: 500,
22 message: e,
23 },
24 }
25 }
26}

Meanwhile, add the resolver inside app.js file and define schema for it.

1const schema = gql`
2 type Post {
3 _id: ID
4 title: String
5 body: String
6 createdUserId: String
7 }
8
9 input createPostInput {
10 title: String
11 body: String
12 createdUserId: String
13 }
14
15 type createPostResponse {
16 success: Boolean
17 data: Post
18 error: Error
19 }
20
21 type Error {
22 status: Int
23 message: String
24 }
25
26 type Query {
27 hello: String
28 }
29
30 type Mutation {
31 createPost(request: createPostInput!): createPostResponse!
32 }
33`

After that, add the resolver in the apollo server

1const resolvers = {
2 Query: {},
3 Mutation: {
4 ...postResolvers,
5 },
6}

Now, it's time to add the subscription to our application. just like query and resolver, we need to add a type definition and resolver for the subscription

add the type definition for subscription in the schema

1type Subscription {
2 postCreated: Post
3 }

Like i said before, subscription work with the concepts of PubSub. if you are new to PubSub, read this article to know about it better.

basically, it is a publish-subscriber pattern where publisher publish an event with a message, subribers who subscribed to it will receive the message.

create a file to initialize the PubSub in the application

1import { PubSub } from "apollo-server"
2
3import * as PUBSUB_EVENTS from "./topics"
4export const EVENTS = {
5 TOPIC: PUBSUB_EVENTS,
6}
7
8export default new PubSub()

For the sake of maintanability, the event are separated and imported into the file.

create a file called topic.js and add the events,

1export const POST_CREATED = "POST_CREATED"

After that, we need to add publish event to the mutation resolver. here, API(Mutation) is the publisher. Add the publish method inside the Mutation Resolver

1pubsub.publish(EVENTS.TOPIC.POST_CREATED, {
2 postCreated: { postCollection },
3})

That's it for the publishing events. Now, it is time to create Subscription inside resolvers,

add the following code inside resolvers

1Subscription: {
2 postCreated: {
3 subscribe: () => {
4 return pubsub.asyncIterator(EVENTS.TOPIC.POST_CREATED)
5 }
6 }
7}

Demo

Finally, It's time to test Subscriptions.. let's do it :-)

Run the Server and Subscription before Mutation API call.

Subscription will by running asynchronously, once Mutation is successful. you can able to see the data in subscription tab.

https://youtu.be/AFoAMwsPrEw

Author

Hey, I’m Ganesh, Full stack engineer.I love to write technical content and help developers like me to grow in the industry. please consider supporting me.

To Read More

Building a Production-grade Nodejs,...

This article is the first part of building a production grade nodejs,graphql and...

Modern React Redux Tutorials with R...

This tutorial explain how you can build an application using modern react redux ...

Building a Piano with React Hooks

In this article, we will see how to build a piano with react hooks. Building a P...

TypeScript Basics - The Definitive ...

In this article, we will learn some basics of typescript which helps you to deve...

Here's why podman is more secured t...

In this article we will see about podman and why it is more secured way to run c...

Building a Production - Ready Node....

In this article, we will see how to build a Nodejs, TypeScript Application and d...

Nginx for Front-end Developers

This article is to explain Nginx for Front-end Developers in a much simpler way....

What is gRPC ? How to implement gRP...

Everyone talks about gRPC. Have you ever wonder how it works or how to implement...