KEMBAR78
Implementing GraphQL API in Elixir – Victor Deryagin | PDF
Implementing GraphQL API in Elixir
By Victor Deryagin, Wise Engineering
What?
● GraphQL
● Our team’s experience of using Elixir for implementing TpT Graph API
● Other random thoughts and opinions . It will be fun
GraphQL
● Alternative web service architecture
● Released by Facebook in 2015
● Single HTTP endpoint, POST, with
query itself in payload
● Shape of response determined by
query
● Client-oriented
Query/result example (GitHub API)
GraphQL == types + relationships
● Schema is defined on server
● Strict-ish type system
○ Basic scalar types:
Int/Float/String/Boolean/Id
○ lists/objects/enums/unions
● Queries - get stuff
● Mutations - change stuff
● Subscriptions - get stream of
stuff being changed
Resources
● https://graphql.org/learn
● https://facebook.github.io/graphql/draft
● Elixir Club 10 talk - “Craft effective API with GraphQL and
Absinthe”
● Book: “Craft GraphQL APIs in Elixir with Absinthe”
Teachers Pay
Teachers
● open since 2006
● 5m+ active users (⅔ of teachers in US)
● 3m+ products
● ~60 engineers
TpT infrastructure
● AWS
● Terraform/Kubernetes/Docker
● MySQL, Redis, Memcached
● Hundreds of nodes
TpT Graph API
● Almost 2 years old
● 2k rps
● Handles significant proportion of work
● Almost all new backend feature
development happens here
Server stack
● Elixir
● Phoenix (mostly its router)
● Absinthe
● Ecto, connected to legacy data stores
Client stack
● React
● Apollo client (js & iOS)
● Redux
Challenges
● Access control
● Schema structure
● Updating schema over time
● Keeping Apollo Client happy
● N+1 queries
● Multiprocessing
● Absinthe-specific stuff
○ Middleware (batching, async, etc.)
○ Absinthe pipeline
Introspection
Enables powerful tools, makes
one think carefully about what
is exposed in the schema
Separation of schemas
It’s easy to prevent field from being
resolved, but we need a different approach
to completely hide its existence
Structuring the schema
Nested objects allow to contain complexity
Access control for free
You only have to worry about limiting
access to one field, everything under it is
going to be protected
Batching
● Absinthe.Middleware.Batch
● DataLoader: https://github.com/absinthe-graphql/dataloader
Evolving schema
● Not too hard for private API
● Announce beforehand, make sure field/object usage is being monitored, in case there are
remaining unchanged clients
● Pay more attention to schema design upfront, consider possible future changes, design for
extensibility
Pleasing Apollo Client
● Make sure there are IDs on everything
● Being as specific as possible with mutations
● Wrapping mutation arguments in object, for easier subsequent changes
● Separate type for each mutation result, also for extensibility in the future
● Make sure to return everything that has changed, with ID attached
● Partial results can be a challenge
Using multiple BEAM processes for handling
request
● Async and batched resolvers execute in separate processes
● Information specific to HTTP request is stored in process dictionary
○ Data needed for A/B testing
○ Data used for request tracing
○ Logger metadata
● Using agent to store all request-specific data & wrappers that copy stuff to dictionary of newly
spawned processes
Other Absinthe stuff
● Processing queries is made in stages by phases of Absinthe pipeline
● Query goes through parsing, validation, analysis & execution, until transformed into response
● Custom phases can be inserted anywhere in pipeline
● Separating & batching resolvers to minimize the amount of work performed
Monitoring
● Individual fields/resolvers are easily instrumentable
● Per-pod metrics are useful for detecting runaway BEAM instances
● Some errors are easier to debug then others:
Elixir.ErlangError: erlang error: :failed,
gen_server.erl:812 - :gen_server.terminate/7
Distributed request tracing
Distributed request tracing
● “Dapper” paper by Google: https://ai.google/research/pubs/pub36356
● Zipkin/OpenTracing/Jaeger
● Poor man’s tracint with AWS ALB & X-Amzn-Request-Id header
● Active area of research & development
Testing
● Stateful testing is made harder than necessary by multiple legacy databases
● No async database tests :(
● Lots of GraphQL tests
● Satisfiably fast
● Looking into property testing
Summary
● Pretty happy with Elixir, both language itself, and adoption process
● Still in flux, effort required to stay up to date
● Llibrary ecosystem has some room for improvement, especially in breadth department
● Turned out to be easy to learn, including people with no fp background
● OTP with processes and supervision trees takes some getting used to
● GraphQL has a big potential, some rough edges still remain
More talks about Elixir @ TpT
● ElixirConf 2017 - Scaling up Elixir at TpT - Shanti Chellaram
https://youtu.be/RwJAETlVrvs
● EMPEX LA 2018 - Panel: Elixir Adoption with Shanti Chellaram & Brandon Richey
https://youtu.be/2TZOtdX1IAI
● Shanti Chellaram: The Best of Both Worlds: High Performance Recommendations with Elixir NIFs
https://youtu.be/iL50Ss6Y85k
Thanks!
Victor Deryagin
vderyagin@gmail.com
https://wise-engineering.com
Questions?

Implementing GraphQL API in Elixir – Victor Deryagin

  • 1.
    Implementing GraphQL APIin Elixir By Victor Deryagin, Wise Engineering
  • 2.
    What? ● GraphQL ● Ourteam’s experience of using Elixir for implementing TpT Graph API ● Other random thoughts and opinions . It will be fun
  • 3.
    GraphQL ● Alternative webservice architecture ● Released by Facebook in 2015 ● Single HTTP endpoint, POST, with query itself in payload ● Shape of response determined by query ● Client-oriented
  • 4.
  • 5.
    GraphQL == types+ relationships ● Schema is defined on server ● Strict-ish type system ○ Basic scalar types: Int/Float/String/Boolean/Id ○ lists/objects/enums/unions ● Queries - get stuff ● Mutations - change stuff ● Subscriptions - get stream of stuff being changed
  • 6.
    Resources ● https://graphql.org/learn ● https://facebook.github.io/graphql/draft ●Elixir Club 10 talk - “Craft effective API with GraphQL and Absinthe” ● Book: “Craft GraphQL APIs in Elixir with Absinthe”
  • 7.
    Teachers Pay Teachers ● opensince 2006 ● 5m+ active users (⅔ of teachers in US) ● 3m+ products ● ~60 engineers
  • 8.
    TpT infrastructure ● AWS ●Terraform/Kubernetes/Docker ● MySQL, Redis, Memcached ● Hundreds of nodes
  • 9.
    TpT Graph API ●Almost 2 years old ● 2k rps ● Handles significant proportion of work ● Almost all new backend feature development happens here
  • 10.
    Server stack ● Elixir ●Phoenix (mostly its router) ● Absinthe ● Ecto, connected to legacy data stores
  • 11.
    Client stack ● React ●Apollo client (js & iOS) ● Redux
  • 12.
    Challenges ● Access control ●Schema structure ● Updating schema over time ● Keeping Apollo Client happy ● N+1 queries ● Multiprocessing ● Absinthe-specific stuff ○ Middleware (batching, async, etc.) ○ Absinthe pipeline
  • 13.
    Introspection Enables powerful tools,makes one think carefully about what is exposed in the schema
  • 14.
    Separation of schemas It’seasy to prevent field from being resolved, but we need a different approach to completely hide its existence
  • 15.
    Structuring the schema Nestedobjects allow to contain complexity
  • 16.
    Access control forfree You only have to worry about limiting access to one field, everything under it is going to be protected
  • 17.
    Batching ● Absinthe.Middleware.Batch ● DataLoader:https://github.com/absinthe-graphql/dataloader
  • 19.
    Evolving schema ● Nottoo hard for private API ● Announce beforehand, make sure field/object usage is being monitored, in case there are remaining unchanged clients ● Pay more attention to schema design upfront, consider possible future changes, design for extensibility
  • 20.
    Pleasing Apollo Client ●Make sure there are IDs on everything ● Being as specific as possible with mutations ● Wrapping mutation arguments in object, for easier subsequent changes ● Separate type for each mutation result, also for extensibility in the future ● Make sure to return everything that has changed, with ID attached ● Partial results can be a challenge
  • 21.
    Using multiple BEAMprocesses for handling request ● Async and batched resolvers execute in separate processes ● Information specific to HTTP request is stored in process dictionary ○ Data needed for A/B testing ○ Data used for request tracing ○ Logger metadata ● Using agent to store all request-specific data & wrappers that copy stuff to dictionary of newly spawned processes
  • 22.
    Other Absinthe stuff ●Processing queries is made in stages by phases of Absinthe pipeline ● Query goes through parsing, validation, analysis & execution, until transformed into response ● Custom phases can be inserted anywhere in pipeline ● Separating & batching resolvers to minimize the amount of work performed
  • 23.
    Monitoring ● Individual fields/resolversare easily instrumentable ● Per-pod metrics are useful for detecting runaway BEAM instances ● Some errors are easier to debug then others: Elixir.ErlangError: erlang error: :failed, gen_server.erl:812 - :gen_server.terminate/7
  • 24.
  • 25.
    Distributed request tracing ●“Dapper” paper by Google: https://ai.google/research/pubs/pub36356 ● Zipkin/OpenTracing/Jaeger ● Poor man’s tracint with AWS ALB & X-Amzn-Request-Id header ● Active area of research & development
  • 26.
    Testing ● Stateful testingis made harder than necessary by multiple legacy databases ● No async database tests :( ● Lots of GraphQL tests ● Satisfiably fast ● Looking into property testing
  • 27.
    Summary ● Pretty happywith Elixir, both language itself, and adoption process ● Still in flux, effort required to stay up to date ● Llibrary ecosystem has some room for improvement, especially in breadth department ● Turned out to be easy to learn, including people with no fp background ● OTP with processes and supervision trees takes some getting used to ● GraphQL has a big potential, some rough edges still remain
  • 28.
    More talks aboutElixir @ TpT ● ElixirConf 2017 - Scaling up Elixir at TpT - Shanti Chellaram https://youtu.be/RwJAETlVrvs ● EMPEX LA 2018 - Panel: Elixir Adoption with Shanti Chellaram & Brandon Richey https://youtu.be/2TZOtdX1IAI ● Shanti Chellaram: The Best of Both Worlds: High Performance Recommendations with Elixir NIFs https://youtu.be/iL50Ss6Y85k
  • 29.
  • 30.