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

Life with GraphQL

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Life with GraphQL

Minsk.rb

Avatar for Roman Dubrovsky

Roman Dubrovsky

February 20, 2020
Tweet

More Decks by Roman Dubrovsky

Other Decks in Programming

Transcript

  1. with ❤from datarockets In this talk • Our adventure with

    GraphQL API: from small component on some pages to the SPA which includes the big part of application functionality • Real issues we faced during creating and supporting our GraphQL API • Issues I discussed with people on afterparties • Unresolved issues and my ideas and vision on designing the GraphQL API • Why I love GraphQL ❤ 8
  2. with ❤from datarockets Our GraphQL experience • Almost 3 years

    of GraphQL API development for our SPA • Made GraphQL API public for our customers • Integrated with a number of external GraphQL APIs • Drunk about 100 bottles of beer discussing GraphQL on afterparties 9
  3. with ❤from datarockets Our GraphQL experience • Almost 3 years

    of GraphQL API development for our SPA • Made GraphQL API public for our customers • Integrated with a number of external GraphQL APIs • Drunk about 100 bottles of beer discussing GraphQL on afterparties 10
  4. with ❤from datarockets Our GraphQL experience • Almost 3 years

    of GraphQL API development for our SPA • Made GraphQL API public for our customers • Integrated with a number of external GraphQL APIs • Drunk about 100 bottles of beer discussing GraphQL on afterparties • It was almost one year ago 11
  5. with ❤from datarockets Our GraphQL experience • Almost 3 years

    of GraphQL API development for our SPA • Made GraphQL API public for our customers • Integrated with a number of external GraphQL APIs • Drunk about 100 bottles of beer discussing GraphQL on afterparties • It was almost one year ago 12
  6. with ❤from datarockets Query type 32 QueryType me request query

    { me { // .... } } organization(id) User Organization
  7. with ❤from datarockets Expectation request query { me { items

    { id } } } 50 response { "data": { "me": { "items": [ { "id": "1" }, { "id": "2" }, // ... ] } }
  8. with ❤from datarockets Reality request query { me { items

    { id } } } 51 response { "data": { "me": { "items": [ { "id": "MDEwOJlcG9zaXRcvnkzMDAxNzMzQA==" }, { "id": "MDEwOJlcG9zaXRcvnkzMDAxNjQ5Mg==" }, // ... ] } } } https://facebook.github.io/relay/graphql/objectidentification.html
  9. with ❤from datarockets Summary • GraphQL works really great if

    you follow Rails development best-practice • You should remember and process GraphQL ID differently 55
  10. with ❤from datarockets request query { me { items {

    id title } } } 59 response { "data": { "me": { "items": [ { "id": "1", "title": "Hello world!!!" }, { "id": "2", "title": "Hello GraphQL!!!" }, // and more 100500 items... ] } }
  11. with ❤from datarockets request query { me { items(per_page: 2)

    { id title } } } 62 response { "data": { "me": { "items": [ { "id": "1", "title": "Hello world!!!" }, { "id": "2", "title": "Hello GraphQL!!!" } ] } } }
  12. with ❤from datarockets request query { me { items(first: 2)

    { nodes { id title } pageInfo { endCursor hasNextPage } } } } 69 response { "data": { "me": { "items": { "nodes": [ { "id": "1", "title": "Hello world!!!" }, { "id": "2", "title": "Hello GraphQL!!!" } ], "pageInfo": { "endCursor": "Y3Vyc29yOnYyOpHOAnq2TA==", "hasNextPage": true }
  13. with ❤from datarockets Using mutation • Create a mutation which

    generates a token for access to the API • It’s still may work for login/password authentication • It would be harder to implement authentication via OAuth since we need to process redirects • It’s hard to update all the data after successful authentication • Maybe, this still makes sense. 73
  14. with ❤from datarockets • Authorize the user to perform some

    mutation • Create per-field “helpers” for verifying access for making changes • Scope data • Get access to only some private fields 77
  15. with ❤from datarockets Exposing authorization rules in the API 79

    request query { me { items(first: 2) { nodes { id canEdit } } } } response { "data": { "me": { "items": { "nodes": [ { "id": "1", "canEdit": true }, { "id": "2", "canEdit": false } ] }
  16. with ❤from datarockets Field authorization request query { items {

    edges { node { title description privateStatistic { viewerCount linkClicksCount } } } } } 81 response What is here?
  17. with ❤from datarockets Field authorization request query { items {

    edges { node { title description privateStatistic { viewerCount linkClicksCount } } } } } 82 response { "error": { "message": "Not Authorized" } }
  18. with ❤from datarockets Field authorization request query { items {

    edges { node { title description privateStatistic { viewerCount linkClicksCount } } } } } 83 response "data": { "items": { "edges": [ { "node": { "title": "Hello world", "description": "C++ in 21 days", "privateStatistic": null, } }, { "node": { "title": "Hello GraphQL", "description": "GraphQL in 35 minut "privateStatistic": { "viewerCount": 100500, "linkClicksCount": 0 },
  19. with ❤from datarockets Field authorization request query { item(id: $id)

    { title description } } 84 response { "data": { "item": null } }
  20. with ❤from datarockets Field authorization • Nullable fields for controlling

    access to some fields • The same result for not found and access denied errors • No error messages on why we can’t get access to a field • For collections we use null when user doesn’t have access and empty list [] if there are no items • This is more about API design not about the implementation 85
  21. with ❤from datarockets Field authorization • Nullable fields for controlling

    access to some fields • The same result for not found and access denied errors • No error messages on why we can’t get access to a field • For collections we use null when user doesn’t have access and empty list [] if there are no items • This is more about API design not about the implementation • GraphQL spec knows how to resolve this issue but Ruby implementation does not. 86
  22. with ❤from datarockets request query { items(first: 50) { nodes

    { id user { name } } } } 89 response { "data": { "items": { "nodes": [ { "id": "1", "user": { "name": "Vasya Pupkin" } }, { "id": "2", "user": { "name": "Ivan Ivanov" } }, // ... ]
  23. with ❤from datarockets field :user, Types::UserType, cache: {key: :user_id}, null:

    false 96 https://github.com/stackshareio/graphql-cache
  24. with ❤from datarockets Query type 108 QueryType me request query

    { me { // .... } } organization(id) User Organization
  25. with ❤from datarockets 111 request query { items(first: 50) {

    nodes { id user { name } } } item(id: "MDEwOJlcG9zaXRcvnkzMDAxNzMzQA==") { title } }
  26. with ❤from datarockets 113 request query { items(first: 50) {

    nodes { id rawContent: content(format: RAW) content(format: MARKUP) } } }
  27. with ❤from datarockets Summary • GraphQL is a great process

    and care about all members of the team • Graphql is a great convention for communication between developers • It does not affect you business logic • It resolver some issues and makes a new one • No worries about formats and versioning • Fun !!!! 136
  28. with ❤from datarockets • Subscription Types • Input Types •

    Working with IDs • Visibility • Supporting deprecated types and fields • Converting GraphQL schema from AR schema • Other approaches using GraphQL • Using GraphQL queries with REST endpoint (e.g. Facebook API) • Monitoring GraphQL schema • Tests for GraphQL schema • etc... 137
  29. with ❤from datarockets • Subscription Types • Input Types •

    Working with IDs • Visibility • Supporting deprecated types and fields • Converting GraphQL schema from AR schema • Other approaches using GraphQL • Using GraphQL queries with REST endpoint (e.g. Graph API) • Monitoring GraphQL schema • Tests for GraphQL schema • etc... 138