Getting Started with Subscriptions

To get started with subscriptions you need a GraphQL server with subscription capabilities.

Example using Apollo and WebSockets

For this example, we will use Apollo and graphql-ws.

Setting up the server

Install the following dependencies:

npm i --save ws graphql-ws neo4j-driver @neo4j/graphql express @apollo/server body-parser cors

The following code implements a simple @apollo/server server with subscriptions. You can find more examples and documentation on subscriptions in Apollo’s documentation.

import { ApolloServer } from "@apollo/server";
import { expressMiddleware } from "@apollo/server/express4";
import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer";
import bodyParser from 'body-parser';
import cors from "cors";
import { createServer } from "http";
import neo4j from 'neo4j-driver';
import { Neo4jGraphQL, Neo4jGraphQLSubscriptionsSingleInstancePlugin } from '@neo4j/graphql';
import { WebSocketServer } from "ws";
import { useServer } from "graphql-ws/lib/use/ws";
import express from 'express';

const typeDefs = `
    type Movie {
        title: String
    }

    type Actor {
        name: String
    }
`;

const driver = neo4j.driver("bolt://localhost:7687", neo4j.auth.basic("neo4j", "password"));

const neoSchema = new Neo4jGraphQL({
    typeDefs,
    driver,
    plugins: {
        subscriptions: new Neo4jGraphQLSubscriptionsSingleInstancePlugin(),
    },
});

async function main() {
    // Apollo server setup with WebSockets
    const app = express();
    const httpServer = createServer(app);
    const wsServer = new WebSocketServer({
        server: httpServer,
        path: "/graphql",
    });

    // Neo4j schema
    const schema = await neoSchema.getSchema();

    const serverCleanup = useServer(
        {
            schema,
            context: (ctx) => {
                return ctx;
            },
        },
        wsServer
    );

    const server = new ApolloServer({
        schema,
        plugins: [
            ApolloServerPluginDrainHttpServer({
                httpServer
            }),
            {
                async serverWillStart() {
                    return Promise.resolve({
                        async drainServer() {
                            await serverCleanup.dispose();
                        },
                    });
                },
            },
        ],
    });
    await server.start();

    app.use(
        "/graphql",
        cors(),
        bodyParser.json(),
        expressMiddleware(server, {
            context: async ({ req }) => ({ req }),
        })
    );

    const PORT = 4000;
    httpServer.listen(PORT, () => {
        console.log(`Server is now running on http://localhost:${PORT}/grahpql`);
    });
}

main();
The example above uses the single instance plugin and cannot scale horizontally.

GraphQL subscriptions

With the previous server running, we have subscriptions available for Movie and Actor. We can subscribe to new movies created with the following statement:

subscription {
    movieCreated(where: { title: "The Matrix" }) {
        createdMovie {
            title
        }
    }
}

Any new movie created with the matching title will trigger a subscription. You can try this with the following query:

mutation {
    createMovies(input: [{ title: "The Matrix" }]) {
        movies {
            title
        }
    }
}
This example uses the graphql-ws implementation, if you are using Apollo Studio, make sure to select "graphql-ws" implementation in connection settings.