Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tracking online user with GraphQL Apollo

I need to handle events "user is now online" and "user is now offline" on GraphQL Apollo Node.js server. What's the best way to do it?

My investigation: I pretty sure that I don't need to implement any heartbeat logic, because subscriptions are working on WebSockets. But I didn't find any info in their docs how to handle WebSockets events like "connecting" and "disconnecting" from the subscription... Actually I can handle those events from the outside of actual subscription:

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

But can't determine which user is connected via this socket.

My implementation: for now I made it work like that:

  1. We have express middleware for all the calls, it is pushing user object from jsonwebtoken to req object. Here I can trigger "user is now online" logic.

  2. I've created separate subscription, client subscribes on it on login and unsubscribes on logout. Since there is no unsubscribe handler, I manage to determine that filter function gets called on user disconnect without payload, so I did this approach:

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

As for me, the solution above is ugly. Can someone recommend the better approach?

like image 418
Andrew Gura Avatar asked Jan 19 '18 09:01

Andrew Gura


People also ask

Does Apollo client cache?

Overview. Apollo Client stores the results of your GraphQL queries in a local, normalized, in-memory cache. This enables Apollo Client to respond almost immediately to queries for already-cached data, without even sending a network request. The Apollo Client cache is highly configurable.

What is difference between useQuery and useLazyQuery?

Unlike with useQuery , when you call useLazyQuery , it does not immediately execute its associated query. Instead, it returns a query function in its result tuple that you call whenever you're ready to execute the query.

What is Apollo tracing?

Apollo Tracing is a GraphQL extension for performance tracing. Thanks to the community, Apollo Tracing already works with most popular GraphQL server libraries, including Node, Ruby, Scala, Java, Elixir, Go and . NET, and it enables you to easily get resolver-level performance information as part of a GraphQL response.

Does Apollo client use Fetch?

A fetch policy defines how Apollo Client uses the cache for a particular query. The default policy is cache-first , which means Apollo Client checks the cache to see if the result is present before making a network request. If the result is present, no network request occurs.


1 Answers

I used this approach

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'))
  })
}
like image 99
Medet Tleukabiluly Avatar answered Nov 16 '22 03:11

Medet Tleukabiluly