GraphQL Subscriptions

GraphQL Subscriptions

All of us know GraphQL subscriptions are meant to build real time applications. But what’s behind the scenes is rarely talked about. What are subscriptions really? Why do they exist? How do we make a case for subscriptions to our managers?

5fef485de4c666c0cf5a7c24bcdd289e?s=128

Kamlesh Chandnani

April 13, 2019
Tweet

Transcript

  1. Subscribe! @_kamlesh_ @peri_nikhil

  2. Kamlesh Chandnani Associate Architect - Frontend @_kamlesh_

  3. Peri Nikhil Engineer, Tech Evangelist, OSS Enthusiast @peri_nikhil

  4. Enough! Let’s talk about building the thing " @_kamlesh_ @peri_nikhil

  5. What are Subscriptions? @_kamlesh_ @peri_nikhil

  6. Subscriptions return data to the client every time an event

    happens on the server @_kamlesh_ @peri_nikhil
  7. Subsription is a root level type like Query and Mutation

    const typeDefs = gql` type Subscription { postAdded: Post } type Query { posts: [Post] } type Mutation { addPost( author: String, comment: String, ): Post } type Post { author: String comment: String } ` @_kamlesh_ @peri_nikhil
  8. Let's look at a typical GraphQL flow! @_kamlesh_ @peri_nikhil

  9. HTTP POST GraphQL Document HTTP Server (Express) GraphQL Server PARSE

    GraphQL Language VALIDATE Schema EXECUTE Resolvers Courtesy: Robert Zhu
  10. HTTP Server (Express) GraphQL Server PARSE GraphQL Language VALIDATE Schema

    EXECUTE Resolvers HTTP POST GraphQL Document @_kamlesh_ @peri_nikhil
  11. HTTP Server (Express) GraphQL Server PARSE GraphQL Language VALIDATE Schema

    EXECUTE Resolvers GraphQL Document @_kamlesh_ @peri_nikhil
  12. HTTP Server (Express) GraphQL Server PARSE GraphQL Language VALIDATE Schema

    EXECUTE Resolvers GraphQL Document @_kamlesh_ @peri_nikhil
  13. HTTP Server (Express) GraphQL Server PARSE GraphQL Language VALIDATE Schema

    EXECUTE Resolvers GraphQL Document @_kamlesh_ @peri_nikhil
  14. HTTP Server (Express) GraphQL Server PARSE GraphQL Language VALIDATE Schema

    EXECUTE Resolvers GraphQL Response @_kamlesh_ @peri_nikhil
  15. HTTP Server (Express) GraphQL Server PARSE GraphQL Language VALIDATE Schema

    EXECUTE Resolvers GraphQL Response @_kamlesh_ @peri_nikhil
  16. Let's see how Subscriptions fit into this @_kamlesh_ @peri_nikhil

  17. WS:Subscribe GraphQL Document Subscriptions Server (WS) GraphQL Server PARSE GraphQL

    Language VALIDATE Schema EXECUTE Resolvers Event System @_kamlesh_ @peri_nikhil
  18. Subscriptions Server (WS) WS:Subscribe GraphQL Document GraphQL Server PARSE GraphQL

    Language VALIDATE Schema EXECUTE Resolvers Event System @_kamlesh_ @peri_nikhil
  19. Subscriptions Server (WS) GraphQL Document GraphQL Server PARSE GraphQL Language

    VALIDATE Schema EXECUTE Resolvers Event System @_kamlesh_ @peri_nikhil Event Stream
  20. Subscriptions Server (WS) GraphQL Document GraphQL Server PARSE GraphQL Language

    VALIDATE Schema EXECUTE Resolvers Event System EVENT @_kamlesh_ @peri_nikhil Event Stream
  21. Subscriptions Server (WS) GraphQL Document GraphQL Server PARSE GraphQL Language

    VALIDATE Schema EXECUTE Resolvers Event System EVENT @_kamlesh_ @peri_nikhil Event Stream
  22. Subscriptions Server (WS) GraphQL Document GraphQL Server PARSE GraphQL Language

    VALIDATE Schema EXECUTE Resolvers Event System EVENT @_kamlesh_ @peri_nikhil Event Stream
  23. Subscriptions Server (WS) GraphQL Document GraphQL Server PARSE GraphQL Language

    VALIDATE Schema EXECUTE Resolvers Event System Executable GraphQL Document @_kamlesh_ @peri_nikhil Event Stream
  24. Subscriptions Server (WS) GraphQL Document GraphQL Server PARSE GraphQL Language

    VALIDATE Schema EXECUTE Resolvers Event System GraphQL Executable Document @_kamlesh_ @peri_nikhil Event Stream
  25. Subscriptions Server (WS) GraphQL Document GraphQL Server PARSE GraphQL Language

    VALIDATE Schema EXECUTE Resolvers Event System GraphQL Executable Document @_kamlesh_ @peri_nikhil Event Stream
  26. Subscriptions Server (WS) GraphQL Document GraphQL Server PARSE GraphQL Language

    VALIDATE Schema EXECUTE Resolvers Event System GraphQL Response @_kamlesh_ @peri_nikhil Event Stream
  27. Subscriptions Server (WS) GraphQL Document GraphQL Server PARSE GraphQL Language

    VALIDATE Schema EXECUTE Resolvers Event System GraphQL Response Event Stream @_kamlesh_ @peri_nikhil
  28. Why can’t I just poll? @_kamlesh_ @peri_nikhil

  29. Client repeatedly initiates a request without knowing if there’s any

    new data.
 @_kamlesh_ @peri_nikhil
  30. Server resources get unnecessarily consumed.
 @_kamlesh_ @peri_nikhil

  31. It’s not real-time, really. @_kamlesh_ @peri_nikhil

  32. So, how would Subscriptions help? @_kamlesh_ @peri_nikhil

  33. We can build real time apps!! @_kamlesh_ @peri_nikhil

  34. You see them everywhere, everyday! @_kamlesh_ @peri_nikhil

  35. Focus on the retweet count and not the tweet @_kamlesh_

    @peri_nikhil
  36. @_kamlesh_ @peri_nikhil

  37. Subscriptions use web sockets under the hood and can be

    accessed using“wss”(websockets) protocol @_kamlesh_ @peri_nikhil wss://graphql.abc.com
  38. What does that even mean? $ @_kamlesh_ @peri_nikhil

  39. The WebSocket specification defines an API establishing "socket" connections between

    a web browser and a server. @_kamlesh_ @peri_nikhil
  40. In plain words: There is a persistent connection between the

    client and the server and either of them can send data at any point of time. @_kamlesh_ @peri_nikhil
  41. HTTPS vs WSS? @_kamlesh_ @peri_nikhil

  42. HTTPS vs WSS? Wrong question to ask @_kamlesh_ @peri_nikhil

  43. HTTP works in the form of request- response pair, where

    in the client always sends a request and server responds to that request @_kamlesh_ @peri_nikhil
  44. HTTP Server Client Can I have a ? request response

    Here you go @_kamlesh_ @peri_nikhil
  45. In contrast WebSocket(“wss”) is a full duplex connection where either

    the server or the client can send data at any point of time. @_kamlesh_ @peri_nikhil
  46. Websocket Server Client Sure Beers Whiskey Can we be friends?

    @_kamlesh_ @peri_nikhil
  47. Quit blabbering, show us an actual demo! @_kamlesh_ @peri_nikhil

  48. What’s happening behind the scenes? @_kamlesh_ @peri_nikhil

  49. Client Server PubSub Impl. Event Stream Subscribe Publish Messaging System

    Publish Subscribe @_kamlesh_ @peri_nikhil
  50. Wait! What is PubSub?
 " @_kamlesh_ @peri_nikhil

  51. PubSub is a form of service- service communication pattern @_kamlesh_

    @peri_nikhil
  52. PubSub keeps a track of who subscribed to what. @_kamlesh_

    @peri_nikhil
  53. In a nutshell PubSub is an orchestrator. @_kamlesh_ @peri_nikhil

  54. There are multiple pubsub engine interfaces available:
 •Redis •RabbitMQ •Kafka

    •Google PubSub •MQTT enabled broker •Postgress @_kamlesh_ @peri_nikhil
  55. Won’t a client get ALL events published on the channel?

    @_kamlesh_ @peri_nikhil Client Server PubSub Impl. Event Stream Subscribe Publish Messaging System Publish Subscribe
  56. What if there are concurrent matches? @_kamlesh_ @peri_nikhil

  57. Filter to the rescue @_kamlesh_ @peri_nikhil

  58. Client Server Event Stream Subscribe Filter PubSub Impl. Publish Messaging

    System Publish Subscribe @_kamlesh_ @peri_nikhil
  59. Okay, but show us how these things work in code!

    @_kamlesh_ @peri_nikhil
  60. Live Code?! @_kamlesh_ @peri_nikhil

  61. @_kamlesh_ @peri_nikhil

  62. 2 steps 1. Write a subscription type on server 2.

    Subscribe to it from your client @_kamlesh_ @peri_nikhil
  63. 1. Write a subscription type on server

  64. const typeDefs = gql` type Subscription { matchUpdates( matchId: ID!

    ): Match! } `; @_kamlesh_ @peri_nikhil
  65. const resolvers = { Subscription: { matchUpdates: { subscribe: ()

    => pubsub.asyncIterator([‘matches_updated’]), resolve: (payload, args, context) => context.getMatchById({ matchId: args.matchId }), }, }, }; @_kamlesh_ @peri_nikhil
  66. The Resolver Map for a field on the Subscription type

    takes an object, not a function like Query and Mutation. const resolvers = { Query: { matchesQuery: (parent, args, context) => {...} }, }; const resolvers = { Subscription: { matchUpdates: { subscribe: () => {...}, resolve: (payload, args, context) => {...} }, }, }; Function Object with “subscribe” and “resolve” fields @_kamlesh_ @peri_nikhil
  67. The “subscribe” field describes what events you’re concerned with subscribe:

    () => pubsub.asyncIterator([‘matches_updated’]) Client Server PubSub Impl. Event Stream Subscribe Publish Messaging System Publish Subscribe @_kamlesh_ @peri_nikhil
  68. The “resolve” field figures out what data to send to

    the subscribed clients resolve: (payload, args, context) => context.getMatchById({..}) Client Server Event Stream Subscribe PubSub Impl. Publish Messaging System Publish Subscribe @_kamlesh_ @peri_nikhil
  69. “withFilter” allows the server to filter out events that are

    sent to the client based on some arguments subscribe: withFilter( () => pubsub.asyncIterator([‘matches_updated’]), (payload, args) => payload.matchesAffected.some((match) => match.id === args.matchId), ), Client Server Event Stream Subscribe Filter PubSub Impl. Publish Messaging System Publish Subscribe @_kamlesh_ @peri_nikhil
  70. 2. Subscribe to it from your client @_kamlesh_ @peri_nikhil

  71. Every Query variable will have the “subscribeToMore” function on it

    @_kamlesh_ @peri_nikhil
  72. const unsubscribeMatchUpdates = matchQuery.subscribeToMore({ document: subscriptions.MATCH_UPDATES_SUBSCRIPTION, variables: { matchId, },

    updateQuery: (previousResult, { subscriptionData }) => { if (!subscriptionData.data) return previousResult; return { ...previousResult, matchById: { ...previousResult.matchById, ...subscriptionData.data.matchUpdates, }, }; }, }); @_kamlesh_ @peri_nikhil
  73. Use the “updateQuery” function to merge the new data with

    the Apollo store to update the UI @_kamlesh_ @peri_nikhil
  74. const unsubscribeMatchUpdates = matchQuery.subscribeToMore({ document: subscriptions.MATCH_UPDATES_SUBSCRIPTION, variables: { matchId, },

    updateQuery: (previousResult, { subscriptionData }) => { if (!subscriptionData.data) return previousResult; return { ...previousResult, matchById: { ...previousResult.matchById, ...subscriptionData.data.matchUpdates, }, }; }, }); @_kamlesh_ @peri_nikhil
  75. “subscribeToMore” returns a function to terminate the subscription (unsubscribe) @_kamlesh_

    @peri_nikhil
  76. useEffect(() => { const unsubscribeMatchUpdates = matchQuery.subscribeToMore({ document: subscriptions.MATCH_UPDATES_SUBSCRIPTION, variables:

    {matchId}, updateQuery: (previousResult, { subscriptionData }) => { if (!subscriptionData.data) return previousResult; return {...}; }, }); return () => unsubscribeMatchUpdates(); }, [matchId, matchQuery]); @_kamlesh_ @peri_nikhil
  77. But, how do we really make a case to our

    managers? @_kamlesh_ @peri_nikhil manager you
  78. If you want to build a module which requires real

    time updates, then definitely subscriptions is your way to go @_kamlesh_ @peri_nikhil
  79. You can’t really use polling because it won’t be real

    time and you’ll waste server resources @_kamlesh_ @peri_nikhil
  80. But, why should I use GraphQL Subscriptions? @_kamlesh_ @peri_nikhil

  81. Coz, it is the cleaner soulution, utilising all the benefits

    of Apollo cache and the GraphQL schemas @_kamlesh_ @peri_nikhil
  82. And of course because we all ❤ GraphQL @_kamlesh_ @peri_nikhil

  83. @_kamlesh_ @peri_nikhil That’s all folks! Thank You Repo Url: http://bit.ly/fun-cricket