使用 GraphQL Apollo 跟踪在线用户

Tracking online user with GraphQL Apollo

我需要在 GraphQL Apollo Node.js 服务器上处理事件 "user is now online" 和 "user is now offline"。最好的方法是什么?

我的调查:我很确定我不需要实现任何心跳逻辑,因为订阅在 WebSockets 上运行。但是我没有在他们的文档中找到任何信息如何处理来自订阅的 "connecting" 和 "disconnecting" 等 WebSockets 事件......实际上我可以从实际订阅的外部处理这些事件:

SubscriptionServer.create({
    execute,
    subscribe,
    schema,
    onConnect = (...args) => {
        console.log('User connected')
    },
    onDisconnect = (...args) => {
        console.log('User disconnected')
    }
}, {
    server: ws,
    path: '/subscriptions'
})

但无法确定哪个用户通过此套接字连接。

我的实现:现在我是这样工作的:

  1. 我们有用于所有调用的 express 中间件,它将用户对象从 jsonwebtoken 推送到 req 对象。这里我可以触发"user is now online"逻辑。

  2. 我创建了单独的订阅,客户端在登录时订阅它,在注销时取消订阅。由于没有 unsubscribe 处理程序,我设法确定在用户断开连接时调用过滤器函数而没有有效负载,所以我采用了这种方法:

    userOnlineSubscription: {
        subscribe: withFilter(
            () => pubSub.asyncIterator('userOnlineSubscription'),
                async (payload, variables) => {
                    if (!payload) {
                        // set user offline
                }
                return false
            }
        )
    }
    

至于我,上面的解决方案很难看。有人可以推荐更好的方法吗?

我使用了这种方法

onConnect (connectionParams, webSocket) {
  const userPromise = new Promise((resolve, reject) => {
    if (connectionParams.jwt) {
      jsonwebtoken.verify(
        connectionParams.jwt,
        JWT_SECRET,
        (err, decoded) => {
          if (err) {
            reject(new Error('Invalid Token'))
          }

          resolve(
            User.findOne({
              where: { id: decoded.id }
            })
          )
        }
      )
    } else {
      reject(new Error('No Token'))
    }
  })

  return userPromise.then(user => {
    if (user) {
      return { user: Promise.resolve(user) }
    }

    return Promise.reject(new Error('No User'))
  })
}