👋 Welcome to Summit 2024
...and Realtime data across your graph with federated subscriptions. We're so excited to have you here with us!
In this workshop, you'll learn how to bring realtime data capabilities into our GraphQL API. We'll take an existing supergraph and introduce a chat feature that runs on data throughout the graph.
What you'll learn:
- Define and use the
Subscription
type in a federated graph - Implement HTTP Callbacks between the router and subgraph
- Apply the
@requires
and@external
directives
⚠️ Before the workshop...
Helpful links
Agenda
With all of our setup out of the way, let's talk about the structure of the workshop.
- PART 1: First, we'll discuss the ins and outs of using GraphQL subscriptions in federation. We'll look at a couple ways that we can make subscriptions work, and talk about the method we'll focus on today.
- PART 2: Next, we'll implement our subscription! We'll bring realtime data into our application; router, schema, resolvers, you name it!
- PART 3: After that, we'll tweak our subscription with some inter-graph optimizations! We'll see how we can use data from a different subgraph to influence our subscription events.
- PART 4: Finally, we'll take a closer look at how we can monitor the performance of our subscriptions with telemetry and debuggability.
Sound good? Great! Time to get to know your companion course. (You are here! 📍)
📖 How to use this companion course
You can use this course as a reference throughout the workshop. Here you'll find instructions, code snippets and exercise solutions that we'll be going through in the workshop.
Follow-along: Lessons starting with Follow-along
are designed for you to follow along with the instructor! Do what they're doing, but on your own machines.
Exercise: Lessons starting with Exercise
are designed to be an individual exercise for you to try your best to solve on your own! If you need help, you can pair with someone beside you, flag down a mentor or consult the solution in that same lesson.
What we're building
Want to book a trip to new, exciting, sometimes-fictional places in the vast universe? Enter Airlock!
Airlock is an intergalactic travel app that lets us browse listings and their amenities, make bookings—and soon, we'll be able to chat with our hosts.
Subscriptions in Airlock
Our Airlock app already consists of several subgraphs. The subgraphs we'll interact with today are:
accounts
: guest- and host-specific datamessages
: our ✨NEW✨ subgraph, which we'll stuff with subscription goodness for realtime communication between guests and their hosts- Provided time,
listings
: all the data under the sun about our intergalactic listings and their amenities
Our goal for the messages
subgraph is to subscribe to new messages that are sent in a particular conversation. We're just handling backend logic here: we won't focus on any of the frontend fanciness, but this will provide us with the foundation to build something production-grade.
Test out some operations!
When your graph is all setup, jump into Studio Explorer and test out some operations. The first time you run an operation, Explorer will prompt you for the router's routing URL. By default, we should be running on port 4000.
http://127.0.0.1:4000
Provide an Authorization
header
First, we'll need to provide an Authorization
header to accompany our query. We have a number of different users to choose from, but one particular user is already part of a conversation:
Authorization: Bearer xeno
Test it out! Run the following command to get data about the user you've just authenticated as.
query GetMe {me {idisLoggedInnamelastActiveTimeprofileDescription}}
Now that you're "authenticated", you can create a conversation, get a list of active conversations, a specific conversation, etc. Be sure to always include your Authorization header with every request!
query GetConversations {conversations {messages {textsentFrom {id}}}}
Note: By default, there won't be any messages in this conversation! (We'll get there.)
You can also create a different conversation by scratch. If you're authorized as user "xeno"
, try out creating a new conversation with recipient "dallas"
.
mutation CreateConversationWithRecipient($recipientId: ID!) {createConversation(recipientId: $recipientId) {idcreatedAt}}
And in the Variables panel:
{"recipientId": "dallas"}
Note: Each time you open a tab for a new operation, you'll need to include the auth header specified earlier.
Finally, you can log in your user and log them out again. Try this mutation.
mutation ToggleUserLoggedIn {changeLoggedInStatus {timesuccessmessage}}
Saving operations for the future!
The following operations will come in handy through the remainder of the course. We don't have the schema in place to run all of these operations currently, but we'll get there! Let's save them to a new Operation Collection.
We can do this by opening the operation in a new tab and clicking the Save icon.
This will prompt us to give the operation a name, and select the collection we want to save it to.
Let's add each of these operations so that we can access them more easily in the future.
Subscribe to a conversation
subscription SubscribeToMessagesInConversation($listenForMessageInConversationId: ID!) {listenForMessageInConversation(id: $listenForMessageInConversationId) {textsentTime}}
Send a message to a conversation
mutation SendMessageToConversation($message: NewMessageInput!) {sendMessage(message: $message) {idtextsentTo {idname}}}
Log a user in and out
mutation ToggleUserLoggedIn {changeLoggedInStatus {timesuccessmessage}}
Fetch all of a user's conversations
query GetConversations {conversations {messages {textsentFrom {id}}}}
Subscribe to a conversation (including a user's online status)
subscription SubscribeToMessagesInConversationIncludeOnline($listenForMessageInConversationId: ID!) {listenForMessageInConversation(id: $listenForMessageInConversationId) {textsentTimesentTo {isOnline}}}
Send a message to conversation (including a user's online status)
mutation SendMessageToConversationIncludeOnline($message: NewMessageInput!) {sendMessage(message: $message) {textsentTo {idnameisOnline}}}
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.