$30 off During Our Annual Pro Sale. View Details »

Traversing the GraphQL AST and Calculating Query Costs

joe_re
September 13, 2023

Traversing the GraphQL AST and Calculating Query Costs

GraphQL Tokkyo LT

joe_re

September 13, 2023
Tweet

More Decks by joe_re

Other Decks in Technology

Transcript

  1. Traversing the GraphQL AST and
    Calculating Query Costs
    @joe-re

    View Slide

  2. About me
    ▸ X: @joe_re


    ▸ GitHub: @joe-re


    ▸ Tech Lead at CureApp Inc.


    ▸ One of the organizer of GraphQL
    Tokyo

    View Slide

  3. What are I am talking about today
    ▸ How GraphQL rate limiting differs from REST API


    ▸ Walking through the GraphQL AST by using graphql-js


    ▸ Introduce three examples to walk through GraphQL API based on actual use
    cases from graphql-cost-calculator
    NOTE:

    1. I believe the basic concept is not signi
    fi
    cantly different from other languages. However, this assumes
    NodeJS environment, as I'm not familiar with GraphQL tooling in other languages.


    2. There’s some other libraries to provide a way to calculate a GraphQL cost but I am not talking about
    them today.

    View Slide

  4. The GraphQL API rate limiting is different from REST API’s
    ▸ We can’t simply count the number of queries for GraphQL rate limiting
    because GraphQL query can replace multiple REST API calls.


    ▸ Small queries only consume minimal server resources, but a single complex
    GraphQL query could be equivalent to thousands of REST API calls.


    ▸ Until the server executes actual GraphQL calls, we can’t determine their true
    cost.

    View Slide

  5. Static analysis is important for blocking queries before they are executed
    ▸ It’s the popular way to calculate GraphQL queries cost to use rate limit instead
    of counting number of requests call.


    ▸ This should be done statically by analyzing the query's AST before execution.


    ▸ Because if some huge queries are executed once, it could consume huge
    server resources.

    View Slide

  6. A rate limiting score on GitHub GraphQL API
    Refer: https://docs.github.com/en/graphql/overview/resource-limitations
    3. Although we're returning 60 labels, the API has to connect to each of
    the 5,000 potential total issues to get the list of labels. So, requests for labels
    = 5,000
    2. Although we're returning 50 issues, the API has to connect to each of
    the 100 repositories to get the list of issues. So, requests for issues

    = 100
    4. Total = 5,101
    1. Although we're returning 100 repositories, the API has to connect to the
    viewer's account once to get the list of repositories. So, requests for repositories
    = 1
    5. Dividing by 100 and rounding gives us the
    fi
    nal score of the query: 51

    View Slide

  7. graphql-cost-calculaor
    ▸ It walks through GraphQL queries AST and estimate a cost statically.


    ▸ This library offers means to calculate the cost of query, facilitating rate limiting
    similar to the GiHub GraphQL API.


    ▸ https://github.com/joe-re/graphql-cost-calculator

    View Slide

  8. DEMO

    View Slide

  9. GraphQL queries AST
    Root is OperationDe
    fi
    nition. (Query/Mutation/Subscription)
    Each
    fi
    elds have “kind” property to provide own node type

    View Slide

  10. Using visitor pattern to walk through an AST
    ▸ Refer: https://graphql.org/graphql-js/language/#visitor


    ▸ graphql-js offers a visitor pattern for traversing the GraphQL AST through the
    visit function


    ▸ With the visit function, you can use the enter/leave

    steps to traverse the AST.


    ▸ By specifying named visitors,

    you can target and traverse speci
    fi
    c kinds of nodes.

    View Slide

  11. Three examples to introduce how to walk through GraphQL AST
    ▸ I will introduce three use cases that explain how to walk through a GraphQL
    AST.


    ▸ 1. Counting requests for each unique connection

    2: Resolving Fragment

    3: Identifying Object Type


    ▸ Each example is based on an actual use case from the library, but it has been
    simpli
    fi
    ed for easy understanding.

    View Slide

  12. Example1: Counting requests for each unique connection
    1. When it enters SelectionSet, get
    fi
    rst/last
    from arguments
    2. If it has a
    fi
    rst/last argument, the multiplier
    is incremented and pushed to the stack
    3. If it lacks a
    fi
    rst/last argument,

    the current multiplier value is pushed to the
    stack.
    4. If it’s a connection node, calculates a cost
    based on current multiplier
    5. When it leaves SelectionSet,

    the current multiplier value is reduced from
    the stack.

    View Slide

  13. Example2: Resolving Fragment
    1. First, store all fragment de
    fi
    nitions.
    2. Upon encountering a FragmentSpread, it is
    replaced with the fragment de
    fi
    nition stored
    in the
    fi
    rst step.

    View Slide

  14. Example3: Identifying Object Type
    1. Retrieve the parent type because a parent
    know what type is for each
    fi
    eld.


    While the AST doesn't recognize the actual
    fi
    eld type, the GraphQL Schema does. With
    this combination, you can obtain the actual
    type name.
    2. Obtain the node's
    fi
    eld class from the
    schema.

    This class includes a `.type` attribute that
    provides the actual type name of the
    fi
    eld.

    View Slide

  15. In conclusion
    ▸ It’s easy to walk through GraphQL AST more than you thought.


    ▸ And it’s really fun. 😉


    ▸ Thanks for listening. 🙏

    View Slide