apollo
apollo copied to clipboard
Websocket Memory Leak Bug
my nuxt config
apollo: {
clientConfigs: {
default: '~/plugins/graphql/http.js',
alternativeClient: '~/plugins/graphql/websocket.js',
},
},
https.js -> no memory leak here after testing with siege without alternativeClient
import { InMemoryCache } from 'apollo-cache-inmemory'
export default (context) => {
return {
assumeImmutableResults: true,
httpEndpoint: context.$config.httpEndpoint,
browserHttpEndpoint: context.$config.browserHttpEndpoint,
cache: new InMemoryCache(),
getAuth: () => 'Bearer SAMPLETOKENasjkdkjahsdkhkashdkjahsdkhkashdkhasdjhajsd',
}
}
websocket.js -> if i add alternativeClient sieging will cause a very high memory leak causing node to be unresponsive after some time
import Pusher from 'pusher-js'
import PusherLink from './pusher'
export default (context) => {
const pusherLink = new PusherLink({
pusher: new Pusher(context.$config.pusherKey, {
wsHost: context.$config.wsHostname,
wsPort: context.$config.wsPort,
wssPort: context.$config.wsPort,
disableStats: true,
authEndpoint: context.$config.browserHttpEndpoint + '/subscriptions/auth',
enabledTransports: ['ws', 'wss'],
}),
})
return {
assumeImmutableResults: true,
link: pusherLink,
getAuth: () => 'Bearer SAMPLETOKENasjkdkjahsdkhkashdkjahsdkhkashdkhasdjhajsd',
}
}
pusher.js
import { ApolloLink, Observable } from 'apollo-link'
class PusherLink extends ApolloLink {
constructor(options) {
super()
// Retain a handle to the Pusher client
this.pusher = options.pusher
}
request(operation, forward) {
return new Observable((observer) => {
// Check the result of the operation
forward(operation).subscribe({
next: (data) => {
// If the operation has the subscription extension, it's a subscription
const subscriptionChannel = this._getChannel(data, operation)
if (subscriptionChannel) {
this._createSubscription(subscriptionChannel, observer)
} else {
// No subscription found in the response, pipe data through
observer.next(data)
observer.complete()
}
},
})
})
}
_getChannel(data, operation) {
return !!data.extensions &&
!!data.extensions.lighthouse_subscriptions &&
!!data.extensions.lighthouse_subscriptions.channels
? data.extensions.lighthouse_subscriptions.channels[operation.operationName]
: null
}
_createSubscription(subscriptionChannel, observer) {
const pusherChannel = this.pusher.subscribe(subscriptionChannel)
// Subscribe for more update
pusherChannel.bind('lighthouse-subscription', (payload) => {
if (!payload.more) {
// This is the end, the server says to unsubscribe
this.pusher.unsubscribe(subscriptionChannel)
observer.complete()
}
const result = payload.result
if (result) {
// Send the new response to listeners
observer.next(result)
}
})
}
}
export default PusherLink
I am using pusher api for my websocket connection.
Please help, I don't know how to implement it the right way using nuxt-apollo. I have implemented the same without nuxt using vue-apollo and it is working on another project.
I have found that nuxt on the server side is keeping every websocket connection alive. I can see it in my websocket server that after running a siege, all connections to websocket is still there. Until the socket hangs up
Error: socket hang up
at connResetException (internal/errors.js:613:14)
at Socket.socketOnEnd (_http_client.js:493:23)
at Socket.emit (events.js:326:22)
at endReadableNT (_stream_readable.js:1226:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
Error: read ECONNRESET
at TCP.onStreamRead (internal/stream_base_commons.js:207:27)
Error: connect ECONNREFUSED 127.0.0.1:3000
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1144:16)
How do I do the websocket connection on the client side only?