7. Exercise - Add the subscription resolver
10m

Overview

Now it's time to take care of the for our Subscription . This has a special job, along with a special shape. It's a resolver unlike any other! Once we've taken care of the resolver, we need to make sure our is passing along the right data.

🎯 Goal 1: Implement the function for Subscription.listenForMessageInConversation

🎯 Goal 2: Update the function for Mutation.sendMessage to send the message as the event payload

When your is successfully running, here's what you can expect to see.

https://studio.apollographql.com

A new subscription event reflected in Explorer, along with the mutation response

The Subscription resolver

  1. Start by creating the Subscription.ts file in the resolvers folder. Here's some boilerplate you can use.
resolvers/Subscription.ts
import { Resolvers } from "../__generated__/resolvers-types";
export const Subscription: Resolvers = {
Subscription: {
listenForMessageInConversation: {
// TODO
},
},
};
  1. Right away, we can jump into resolvers/index.ts and uncomment the Subscription import so that it's included in our resolvers map.
import { Query } from "./Query";
import { Mutation } from "./Mutation";
import { Message } from "./Message";
import { Conversation } from "./Conversation";
import { User } from "./User";
import { Subscription } from "./Subscription";
const resolvers = {
...Query,
...Mutation,
...Conversation,
...Message,
...User,
...Subscription,
};
export default resolvers;
  1. Back in resolvers/Subscription.ts, give the listenForMessageInConversation object a subscribe function.
listenForMessageInConversation: {
subscribe: () => {}
},
  1. Destructure the third positional , contextValue, for its pubsub property.
listenForMessageInConversation: {
subscribe: (_, __, { pubsub }) => {}
},
  1. Return the results of calling pubsub.asyncIterator, passing in an array with the event string we're listening for: "NEW_MESSAGE_SENT".
listenForMessageInConversation: {
subscribe: (_, __, { pubsub }) => {
return pubsub.asyncIterator(["NEW_MESSAGE_SENT"])
}
},

At this point, you'll probably see an error from TypeScript about the type that the subscribe function returns. This is a known bug. Currently, there are two workarounds. You can either apply // @ts-ignore to the line just above the error, or you can modify the object returned as shown below under Option 2. Please pick whichever option you like best!

Option 1
listenForMessageInConversation: {
// @ts-ignore
subscribe: (_, __, { pubsub }) => {
return pubsub.asyncIterator(["NEW_MESSAGE_SENT"])
}
},
Option 2
listenForMessageInConversation: {
subscribe: (_, __, {pubsub}) => {
return {
[Symbol.asyncIterator]: () => pubsub.asyncIterator(["NEW_MESSAGE_SENT"])
}
}
},

Want to learn more about the AsyncIterator interface? Check out the MDN Web Docs.

Update the Mutation resolver

The function for Mutation.sendMessage is publishing the right event, but it's not passing anything along with it. In order for our subscribe function to receive the new data, our needs to pass it along as its payload.

Jump to resolvers/Mutation.ts.

  1. Scroll down to where we call pubsub.publish in the Mutation.sendMessage . Currently, we pass a second to this call, an object.
await pubsub.publish("NEW_MESSAGE_SENT", {});
  1. Give the object a key that matches the name of our Subscription .
await pubsub.publish("NEW_MESSAGE_SENT", {
listenForMessageInConversation: // TODO
});
  1. As the value, pass in an object containing only the attributes of the message that are present on the Message type. Hint: Check out the attributes returned by the call to the database. Which ones should we pass along? Do all the names match the on Message?
await pubsub.publish("NEW_MESSAGE_SENT", {
listenForMessageInConversation: {
id,
text: messageText,
sentFrom,
sentTo,
sentTime,
},
});

Try it out!

Return to Studio Explorer. Let's build some !

Running a subscription

We'll start by subscribing to a particular conversation. Open up the SubscribeToMessagesInConversation from your Operation Collection; alternatively, copy it below.

subscription SubscribeToMessagesInConversation(
$listenForMessageInConversationId: ID!
) {
listenForMessageInConversation(id: $listenForMessageInConversationId) {
text
sentTime
}
}

And in the Variables panel:

{
"listenForMessageInConversationId": "xeno-ripley-chat"
}

This should kick off the in the right-hand Response panel (a little window labeled Subscriptions should appear near the bottom).

Next, open up a new tab. Here, we'll trigger a to send a message to that conversation (SendMessageToConversation from your Collection).

mutation SendMessageToConversation($message: NewMessageInput!) {
sendMessage(message: $message) {
id
text
sentTo {
id
name
}
}
}

And in the Variables panel:

{
"message": {
"text": "I hope there are no hard feelings about before!",
"conversationId": "xeno-ripley-chat"
}
}

Note: To participate in conversation "xeno-ripley-chat", you should be authenticated as either user "xeno" or "ripley". (This means that your Authorization header should have the value Bearer xeno or Bearer ripley.)

https://studio.apollographql.com

A new subscription event reflected in Explorer, along with the mutation response

Try updating your Authorization header - and sending a response from the other participant in the conversation!

Previous

Share your questions and comments about this lesson

Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.