Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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?

Kamlesh Chandnani

April 13, 2019
Tweet

More Decks by Kamlesh Chandnani

Other Decks in Technology

Transcript

  1. Subscribe!
    @_kamlesh_ @peri_nikhil

    View Slide

  2. Kamlesh Chandnani
    Associate Architect - Frontend
    @_kamlesh_

    View Slide

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

    View Slide

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

    View Slide

  5. What are Subscriptions?
    @_kamlesh_ @peri_nikhil

    View Slide

  6. Subscriptions return data to
    the client every time an event
    happens on the server
    @_kamlesh_ @peri_nikhil

    View Slide

  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

    View Slide

  8. Let's look at a typical
    GraphQL flow!
    @_kamlesh_ @peri_nikhil

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  16. Let's see how
    Subscriptions fit into this
    @_kamlesh_ @peri_nikhil

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

  28. Why can’t I just poll?
    @_kamlesh_ @peri_nikhil

    View Slide

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

    @_kamlesh_ @peri_nikhil

    View Slide

  30. Server resources get unnecessarily consumed.

    @_kamlesh_ @peri_nikhil

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  36. @_kamlesh_ @peri_nikhil

    View Slide

  37. Subscriptions use web sockets under the
    hood and can be accessed
    using“wss”(websockets) protocol
    @_kamlesh_ @peri_nikhil
    wss://graphql.abc.com

    View Slide

  38. What does that even mean?
    $
    @_kamlesh_ @peri_nikhil

    View Slide

  39. The WebSocket specification
    defines an API establishing
    "socket" connections between a
    web browser and a server.
    @_kamlesh_ @peri_nikhil

    View Slide

  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

    View Slide

  41. HTTPS vs WSS?
    @_kamlesh_ @peri_nikhil

    View Slide

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

    View Slide

  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

    View Slide

  44. HTTP
    Server
    Client
    Can I have a

    ?
    request
    response
    Here you go

    @_kamlesh_ @peri_nikhil

    View Slide

  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

    View Slide

  46. Websocket
    Server
    Client
    Sure

    Beers

    Whiskey
    Can we be friends?
    @_kamlesh_ @peri_nikhil

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  50. Wait! What is PubSub?

    "
    @_kamlesh_ @peri_nikhil

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  54. There are multiple pubsub engine interfaces available:

    •Redis
    •RabbitMQ
    •Kafka
    •Google PubSub
    •MQTT enabled broker
    •Postgress
    @_kamlesh_ @peri_nikhil

    View Slide

  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

    View Slide

  56. What if there are concurrent matches?
    @_kamlesh_ @peri_nikhil

    View Slide

  57. Filter to the rescue
    @_kamlesh_ @peri_nikhil

    View Slide

  58. Client
    Server
    Event Stream
    Subscribe
    Filter
    PubSub
    Impl.
    Publish Messaging
    System
    Publish
    Subscribe
    @_kamlesh_ @peri_nikhil

    View Slide

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

    View Slide

  60. Live Code?!
    @_kamlesh_ @peri_nikhil

    View Slide

  61. @_kamlesh_ @peri_nikhil

    View Slide

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

    View Slide

  63. 1. Write a subscription type on server

    View Slide

  64. const typeDefs = gql`
    type Subscription {
    matchUpdates(
    matchId: ID!
    ): Match!
    }
    `;
    @_kamlesh_ @peri_nikhil

    View Slide

  65. const resolvers = {
    Subscription: {
    matchUpdates: {
    subscribe: () => pubsub.asyncIterator([‘matches_updated’]),
    resolve: (payload, args, context) => context.getMatchById({
    matchId: args.matchId
    }),
    },
    },
    };
    @_kamlesh_ @peri_nikhil

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  70. 2. Subscribe to it from your client
    @_kamlesh_ @peri_nikhil

    View Slide

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

    View Slide

  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

    View Slide

  73. Use the “updateQuery” function
    to merge the new data with the
    Apollo store to update the UI
    @_kamlesh_ @peri_nikhil

    View Slide

  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

    View Slide

  75. “subscribeToMore” returns a
    function to terminate the
    subscription (unsubscribe)
    @_kamlesh_ @peri_nikhil

    View Slide

  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

    View Slide

  77. But, how do we really make a case to our managers?
    @_kamlesh_ @peri_nikhil
    manager
    you

    View Slide

  78. If you want to build a module which requires real time
    updates, then definitely subscriptions is your way to
    go
    @_kamlesh_ @peri_nikhil

    View Slide

  79. You can’t really use polling because it won’t
    be real time and you’ll waste server resources
    @_kamlesh_ @peri_nikhil

    View Slide

  80. But, why should I use
    GraphQL Subscriptions?
    @_kamlesh_ @peri_nikhil

    View Slide

  81. Coz, it is the cleaner soulution,
    utilising all the benefits of Apollo
    cache and the GraphQL schemas
    @_kamlesh_ @peri_nikhil

    View Slide

  82. And of course because
    we all ❤ GraphQL
    @_kamlesh_ @peri_nikhil

    View Slide

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

    View Slide