如何关闭 Apollo 中 GraphQL 订阅的套接字连接

How to close socket connection for GraphQL subscription in Apollo

我想在用户注销后关闭我的 Apollo 服务器上的 GraphQL 订阅。最初的问题是我们是否应该在客户端或后端关闭此(套接字)连接。

在前端,我将 Angular 与 Apollo Client 一起使用,我通过从 apollo-angular 扩展 Subscription class 来处理 GraphQL 订阅。我可以使用典型的 takeUntil rxjs 实现关闭订阅频道:

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

但是,这不会关闭服务器上的 websocket,如果我是对的,这将导致订阅内存泄漏。

Apollo Server(和 express)为订阅设置的方式如下:

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...
    }

当客户端注册一个新的 GraphQL 订阅时,我总是能在服务器日志上看到 console.log('on connect');,但我从来没有看到 console.log('on Disconnect');,除非我关闭前端应用程序。

我还没有看到任何关于如何使用 Apollo 关闭 websocket 订阅的例子。我这样做主要是为了完成一个Logout的实现。

我是不是漏掉了什么?提前致谢!

我在 Apollo 客户端 GitHub 站点上发布了 my solution 相关讨论。

我的解决方案基于此post

本质上,我们使用套接字创建订阅的方式是使用 subscriptions-transport-ws

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

如问题中所述,我想在用户注销之前取消订阅所有频道并关闭订阅套接字连接。我们通过在注销函数中使用 webSocketClient SubscriptionClient 并调用:

webSocketClient.unsubscribeAll();
webSocketClient.close();