Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GraphQL Subscriptions: Max Listeners Exceeded Warning

We are using GraphQL Subscriptions and pubsub to subscribe to posts.

When more than 10 subscriptions occur we get the the node warning "MaxListenersExceededWarning: Possible EventEmitter memory leak detected."

Is it possible to raise the max listeners in the pubsub class?

The pubsub class is inside a separate module and looks like this:

import { PubSub } from 'graphql-subscriptions';

const pubsub = new PubSub();

export { pubsub };

The subscription server looks like this:

import { SubscriptionManager } from 'graphql-subscriptions';
import { createServer } from 'http';
import { SubscriptionServer } from 'subscriptions-transport-ws';

import { pubsub } from './subscriptions';
import executableSchema from './executableSchema';

const WS_PORT = 8080;

const websocketServer = createServer((request, response) => {
  response.writeHead(404);
  response.end();
});

websocketServer.listen(WS_PORT, () => console.log(
  `Websocket Server is now running on http://localhost:${WS_PORT}`
));

const subscriptionManager = new SubscriptionManager({
  schema: executableSchema,
  pubsub: pubsub,
  setupFunctions: {
        newPost: (options, args) => {
         return {
            newPostChannel: {
               filter: (post) => {
                  return args.publicationId === post.relatedPublication.id;
               }
            },
         };
      },
  },
});

const subscriptionServer = new SubscriptionServer({
  subscriptionManager: subscriptionManager
}, {
  server: websocketServer,
  path: '/',
});


export {
  subscriptionServer,
};
like image 888
Locco0_0 Avatar asked May 03 '17 05:05

Locco0_0


3 Answers

I wrote the original implementation of the graphql-subscriptions package you're using, so I can provide some context here.

The simple EventEmitter pubsub library included in graphql-subscriptions is only intended for demo purposes. EventEmitters don't really scale to large numbers, they're in-memory, and they'll only work as long as you have no more than a single server.

For anyone trying to run GraphQL subscriptions in production, I strongly recommend using a different system, for example Redis or MQTT through graphql-redis-subscriptions or graphql-mqtt-subscriptions. This will have the advantage of keeping the GraphQL server stateless (apart from the websockets) and thus easy to scale horizontally.

like image 79
helfer Avatar answered Nov 11 '22 02:11

helfer


ee is a protected member of PubSub, so setting it directly will cause errors in a TypeScript project. However, you can pass an EventEmitter with an adjusted MaxListener count to the PubSub constructor:

import { PubSub } from 'apollo-server-express';
import { EventEmitter } from 'events';

const biggerEventEmitter = new EventEmitter();
biggerEventEmitter.setMaxListeners(30);
const pubSub = new PubSub({eventEmitter: biggerEventEmitter});
like image 38
Keith Gillette Avatar answered Nov 11 '22 03:11

Keith Gillette


Found out that you can change the max listeners in the event emitter of the pubsub instance, like so:

import { PubSub } from 'graphql-subscriptions';

const pubsub = new PubSub();
pubsub.ee.setMaxListeners(30); // raise max listeners in event emitter

export { pubsub };
like image 4
Locco0_0 Avatar answered Nov 11 '22 03:11

Locco0_0