mercurius-js / mercurius

Implement GraphQL servers and gateways with Fastify
https://mercurius.dev/
MIT License
2.33k stars 234 forks source link

Simple subscription example shown in docs fails to push new notifications to client #1011

Closed gabrielschulhof closed 11 months ago

gabrielschulhof commented 11 months ago

The example at https://github.com/mercurius-js/mercurius/blob/master/docs/subscriptions.md#subscription-support-simple does not seem to result in notifications getting pushed to the client.

Steps to reproduce

Step 1

Flesh out the example into a full-fledged server:

const Fastify = require('fastify')
const mercurius = require('mercurius')

const app = Fastify()

const schema = `
  type Notification {
    id: ID!
    message: String
  }

  type Query {
    notifications: [Notification]
  }

  type Mutation {
    addNotification(message: String): Notification
  }

  type Subscription {
    notificationAdded: Notification
  }
`

let idCount = 1
const notifications = [
  {
    id: idCount,
    message: 'Notification message'
  }
]

const resolvers = {
  Query: {
    notifications: () => notifications
  },
  Mutation: {
    addNotification: async (_, { message }, { pubsub }) => {
      const id = idCount++
      const notification = {
        id,
        message
      }
      notifications.push(notification)
      await pubsub.publish({
        topic: 'NOTIFICATION_ADDED',
        payload: {
          notificationAdded: notification
        }
      })

      return notification
    }
  },
  Subscription: {
    notificationAdded: {
      // You can also subscribe to multiple topics at once using an array like this:
      //  pubsub.subscribe(['TOPIC1', 'TOPIC2'])
      subscribe: async (root, args, { pubsub }) =>
        await pubsub.subscribe('NOTIFICATION_ADDED')
    }
  }
}

app.register(mercurius, {
  schema,
  resolvers,
  subscription: true
}).then(() => app.listen({port: 9999}))

Step 2

Run the server (Node.js 20.0.0, fastify 4.21.0, mercurius 13.1.0)

Step 3

Connect to the server with altair graphql client, setting the request URL to http://localhost:9999/graphql and creating three tabs:

Tab 1:

query notifications {
  notifications {
    message
  }
}

Tab 2:

mutation addNotification($message:String) {
  addNotification(message:$message) {
    message
  }
}

variables:

{"message": "Yoo-hoo!"}

Tab 3:

subscription notificationAdded {
  notificationAdded {
    message
  }
}

URL: ws://localhost:9999/graphql/subscriptions

Step 4

Run the query. This returns a single result.

Step 5

Run the subscription.

Step 6

Run the mutation.

Expected outcome

The subscription tab has a single line on the right-hand-side showing the message that was added.

Actual outcome

Although the query tab, when executed after the mutation, shows two messages in the list, the subscription tab shows no activity.

mcollina commented 11 months ago

Everything is working fine for me when using GraphiQL, so maybe there is something odd in your client?

gabrielschulhof commented 11 months ago

@mcollina yeah, I think that was it. Critically, I wanted to make sure subscriptions work when subscribing using something other than the UI generated by the server itself. Looks like Altair may be faulty in this case. I installed the Electron-wrapped graphql playground and was able to connect to the endpoint just fine. Thanks for doing a quick check!

mcollina commented 11 months ago

Note that there are two protocols for GraphQL over websockets, so your client might be using the other one. I think we support both of them via an option, check it out.