Subscriptions-transport-ws: Subscriptions with Nested connected data returns [Object Object]

Created on 1 Dec 2017  路  5Comments  路  Source: apollographql/subscriptions-transport-ws

I discovered this issue when reviewing the chapter on subscriptions on the How to GraphQL website.

The sample and example works, but If you try to subscribe to connected data you get __[Object object]__ in Graphiql.

In the lesson, the following Subscription type is created:

type Subscription {
  Link(filter: LinkSubscriptionFilter): LinkSubscriptionPayload
}

input LinkSubscriptionFilter {
  mutation_in: [_ModelMutationType!]
}

type LinkSubscriptionPayload {
  mutation: _ModelMutationType!
  node: Link
}

enum _ModelMutationType {
  CREATED
  UPDATED
  DELETED
}

And in the Subscription resolver pubsub is setup...

Subscription: {
  Link: {
    subscribe: () => pubsub.asyncIterator('Link'),
  },
},

And in the create link Resolver a Link event is published

Mutation: {
  createLink: async (root, data, {mongo: {Links}, user}) => {
    assertValidLink(data);
    const newLink = Object.assign({postedById: user && user._id}, data)
    const response = await Links.insert(newLink);

    newLink.id = response.insertedIds[0]
    pubsub.publish('Link', {Link: {mutation: 'CREATED', node: newLink}});

    return newLink;
  },
},

__So far everything works__: in fact if I add the subscription to Graphiql it all works...

subscription {
  Link(filter:{
    mutation_in: [CREATED]
  }) {
    mutation
    node {
      id
      url
      description
    }
  }
}

The Issue...

occurs when I try to request nested link data. In a typical query for __allLinks__ I can connect users through the postedBy resolver. However, in the subscription trying to see the postedBy user info causes the subscription response to break.

__Intended Outcome__: the connected user's data is returned in the subscription.

__Actual Outcome__: [Object, object] is returned by graphiql

__Subscription that causes the problem:__

subscription {
  Link(filter:{
    mutation_in: [CREATED]
  }) {
    mutation
    node {
      id
      url
      description
      postedBy {
          name
      }
    }
  }
}

I noticed that that when a subscription is published the Link resolvers that find the postedBy connection are not invoked:

Link: {
        id: root => root._id || root.id,
        postedBy: async ({postedById}, data, {mongo: {Users}}) => {
            return await Users.findOne({ _id: postedById })
        }
    },

I've tried adding code to find the user directly to the mutation, but the subscription still returns __[Object Object]__

        createLink: async (root, data, {mongo: {Links, Users}, user}) => {
            assertValidLink(data)
            const newLink = Object.assign({ postedById: user && user._id }, data)
            const response = await Links.insert(newLink)
            newLink.id = response.insertedIds[0]
            newLink.postedBy = await Users.findOne({ _id: user._id })
            newLink.postedBy.id = newLink.postedBy._id
            pubsub.publish('Link', { 
                "Link": {
                    mutation: 'CREATED', 
                    node: newLink
                } 
            })
            return newLink
        },

When I use pubsub.publish... how can I make nested resolvers work with subscriptions.

Most helpful comment

After some more digging it turns out that the problem comes from the empty context passed on subscriptions.
@MoonTahoe You can just add the context in the onOperation parameter of the SubscriptionServer.create:

        SubscriptionServer.create(
            {
               execute, subscribe, schema,
               onOperation: (message, params, webSocket) => {
                return { ...params, context: {mongo} }
              },
            },
            { server, path: '/subscriptions' },
        );

Note that I am not passing the user here. You can add it to the context too. (This is specific to the tutorial @MoonTahoe and me have been following)
This issue is related to apollographql/subscriptions-transport-ws#300

All 5 comments

Same issue for me, with the same tutorial.
The [Object object] message seems to be a Graphiql bug. See graphql/graphiql#636

The actual content returned via websocket is:
error

This is for the query:

subscription {
  Link(filter:{mutation_in:[CREATED]}) {
    node {
      url
      description
      postedBy {
        id
        name
      }
    }
  }
}

I think this issue is similar to apollographql/subscriptions-transport-ws#236

There is no dataloader as I wanted to make sure that it wasn't the origin of the issue.

After some more digging it turns out that the problem comes from the empty context passed on subscriptions.
@MoonTahoe You can just add the context in the onOperation parameter of the SubscriptionServer.create:

        SubscriptionServer.create(
            {
               execute, subscribe, schema,
               onOperation: (message, params, webSocket) => {
                return { ...params, context: {mongo} }
              },
            },
            { server, path: '/subscriptions' },
        );

Note that I am not passing the user here. You can add it to the context too. (This is specific to the tutorial @MoonTahoe and me have been following)
This issue is related to apollographql/subscriptions-transport-ws#300

@nharraud, thanks! it works! That took care of it.

For reference, in case anyone is making this change in the lesson...

  1. I had to use Object.assign, the lesson does not setup babel.
  2. I had to pass 'dataloaders', in the lesson we added dataloaders to the context alongside of mongo. You have to do the same with subscriptions
Object.assign(
  params, 
  {
    context: {
       mongo, 
       dataloaders: buildDataloaders(mongo)
    }
  })

in case anyone is making this change in the lesson

@MoonTahoe, I think it would be better if you create an issue in howtographql/howtographql repo about this.

And, actually, I did the same thing when I was studying that tutorial too. 馃憤

Also, this issue can be closed, I believe.

Yea, thanks. I've seen this happen before so I originally though it may be a transport issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

PetrSnobelt picture PetrSnobelt  路  3Comments

AruXc picture AruXc  路  3Comments

corysimmons picture corysimmons  路  5Comments

mjasnikovs picture mjasnikovs  路  5Comments

leshane picture leshane  路  3Comments