最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to close socket connection for GraphQL subscription in Apollo - Stack Overflow

programmeradmin1浏览0评论

I have GraphQL Subscriptions on my Apollo server that I want to close after the user logs out. The initial question is whether we should close this (socket) connections on the client side or in the backend.

On the front-end, I am using Angular with Apollo Client and I handle GraphQL subscriptions by extending the Subscription class from apollo-angular. I am able to close the subscription channels with a typical takeUntil rxjs implementation:

this.userSubscription
  .subscribe()
  .pipe(takeUntil(this.subscriptionDestroyed$))
  .subscribe(
    ({ data }) => {
      // logic goes here
    },
    (error) => {
      // error handling
   }
);
  

However, this does not close the websocket on the server, which If I'm right, will result in a subscription memory leak.

The way the Apollo Server (and express) is set up for subscriptions is as follows:

const server = new ApolloServer({
  typeDefs,
  resolvers,
  subscriptions: {
    onConnect: (connectionParams, webSocket, context) => {
      console.log('on connect');
      const payload = getAuthPayload(connectionParams.accessToken);
      if (payload instanceof Error) {
        webSocket.close();
      }
      return { user: payload };
    },
    onDisconnect: (webSocket, context) => {
      console.log('on Disconnect');
    }
  },
  context: ({ req, res, connection }) => {
    if (connection) {
      // set up context for subscriptions...
    } else {
      // set up context for Queries, Mutations...
    }

When the client registers a new GraphQL subscription, I always get to see console.log('on connect'); on the server logs, but I never see console.log('on Disconnect'); unless I close the front-end application.

I haven't seen any example on how to close the websocket for subscriptions with Apollo. I mainly want to do this to plete a Logout implementation.

Am I missing something here? Thanks in advance!

I have GraphQL Subscriptions on my Apollo server that I want to close after the user logs out. The initial question is whether we should close this (socket) connections on the client side or in the backend.

On the front-end, I am using Angular with Apollo Client and I handle GraphQL subscriptions by extending the Subscription class from apollo-angular. I am able to close the subscription channels with a typical takeUntil rxjs implementation:

this.userSubscription
  .subscribe()
  .pipe(takeUntil(this.subscriptionDestroyed$))
  .subscribe(
    ({ data }) => {
      // logic goes here
    },
    (error) => {
      // error handling
   }
);
  

However, this does not close the websocket on the server, which If I'm right, will result in a subscription memory leak.

The way the Apollo Server (and express) is set up for subscriptions is as follows:

const server = new ApolloServer({
  typeDefs,
  resolvers,
  subscriptions: {
    onConnect: (connectionParams, webSocket, context) => {
      console.log('on connect');
      const payload = getAuthPayload(connectionParams.accessToken);
      if (payload instanceof Error) {
        webSocket.close();
      }
      return { user: payload };
    },
    onDisconnect: (webSocket, context) => {
      console.log('on Disconnect');
    }
  },
  context: ({ req, res, connection }) => {
    if (connection) {
      // set up context for subscriptions...
    } else {
      // set up context for Queries, Mutations...
    }

When the client registers a new GraphQL subscription, I always get to see console.log('on connect'); on the server logs, but I never see console.log('on Disconnect'); unless I close the front-end application.

I haven't seen any example on how to close the websocket for subscriptions with Apollo. I mainly want to do this to plete a Logout implementation.

Am I missing something here? Thanks in advance!

Share Improve this question asked Dec 9, 2020 at 20:13 chrischris 2,8524 gold badges37 silver badges66 bronze badges 2
  • Were you able to figure this out? – p4sh4 Commented Jan 6, 2021 at 8:58
  • 1 @p4sh4 yes, I will post the solution later today – chris Commented Jan 8, 2021 at 16:19
Add a ment  | 

1 Answer 1

Reset to default 4

I based my solution based on this post

Essentially, the way we created the Subscription with sockets was using subscriptions-transport-ws

export const webSocketClient: SubscriptionClient = new 
SubscriptionClient(
  `${environment.WS_BASE_URL}/graphql`,
  {
    reconnect: true,
    lazy: true,
    inactivityTimeout: 3000,
    connectionParams: () => ({
      params: getParams()
    })
  }
);

As specified in the question, I wanted to unsubscribe all channels and close the subscription socket connection before logout of the user. We do this by using the webSocketClient SubscriptionClient in the logout function and call:

webSocketClient.unsubscribeAll();
webSocketClient.close();
发布评论

评论列表(0)

  1. 暂无评论