Apollo Server - GraphQL's subscription websocket connection doesn't persist
Asked Answered
E

0

1

I have been working with graphql subscriptions and have been able to implement it. It works fine without any issues when I host the same on local. But when I deploy it on a server with a idle_timeout set to 'x' seconds, it drops the connection to the client on graphql playground after those 'x' seconds. I am expecting it to persist...

Here is my code

const http = require('http');
const {ApolloServer, gql} = require('apollo-server-express');
const express = require('express');
const db = require('./db');
const { PubSub, withFilter } = require('graphql-subscriptions')
const env = require('./config');
const cors = require('cors');


const pubSub = new PubSub();
const app = express();
app.use(cors());

const typeDefs = gql`
    type Query {
        qflEventTypes: [String]
    }

    type Mutation {
        pushQflData(symbol: String, date: Int, field: String, value: String, type: String) : Boolean
        pushQflDBEvent(event : String, date : Int, factor : String) : Boolean
    }

    type Subscription {
        qflDataChange: qflData
        qflEventChange(eventname : String): qflEvent
    }

    type qflData {
        symbol : String
        date : Int
        field : String
        value : String
        type : String
    }

    type qflEvent {
        event : String
        date : Int
        factor : String
    }
`;

const resolvers = {
    Query: {
        qflEventTypes(){
            return db.qflevents.list().map(a => a.eventname);
        }
    },
    Mutation: {
        pushQflData : (root,{symbol,date,field,value,type}) => {
            pubSub.publish('QFL_DATA_CHANGED', {qflDataChange: {symbol,date,field,value,type}}) 
            return true;
        },
        pushQflDBEvent : (root,{event,date,factor}) => {
            pubSub.publish('QFL_EVENT_CHANGED', {qflEventChange: {event,date,factor}}) 
            return true;
        }
    },
    Subscription: {
        qflDataChange :{
            subscribe: () => pubSub.asyncIterator('QFL_DATA_CHANGED')
        },
        qflEventChange : {
            subscribe: withFilter(() => pubSub.asyncIterator('QFL_EVENT_CHANGED'), (payload, variables) => {
                return payload.qflEventChange.event === variables.eventname;
        })
        }
    }
};


const server = new ApolloServer({
    typeDefs,
    resolvers,
    introspection: true, // enables introspection of the schema
    playground: true, // enables the actual playground
    subscriptions: {
      path: '/api/ws',
      keepAlive: 15000,
      onConnect: () => console.log("connected"),
      onDisconnect: () => console.log("disconnected")
    }
});

server.applyMiddleware({app,path: '/api/ql', cors: false});

const httpServer = http.createServer(app);
server.installSubscriptionHandlers(httpServer);

var port = env.Runtime.PORT || 9000

httpServer.listen(port, () => {
    console.log(`πŸš€ Server ready at http://localhost:${port}${server.graphqlPath}`)
    console.log(`πŸš€ Subscriptions ready at ws://localhost:${port}${server.subscriptionsPath}`)
  })


I have already invested couple days on the same. If anyone can help me out or give me a lead, it shall be helpful.

Earthbound answered 26/3, 2020 at 22:37 Comment(4)
keepAlive is a parameter for setInterval - scaled in miliseconds .... 1000 is simply too low ;) – Department
I actually tried for longer intervals as well 15000 20000, still the same issue – Earthbound
still not too much ... https://mcmap.net/q/273977/-handling-connection-loss-with-websockets/6124657 – Department
Why would the interval being too low be a problem if it's a keep-alive interval? That makes no sense at all. – Grane

© 2022 - 2024 β€” McMap. All rights reserved.