Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Implementing GraphQL API in Elixir – Victor Deryagin

275 views

Published on

Elixir Club 11
June 23, 2018
Ternopil

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Implementing GraphQL API in Elixir – Victor Deryagin

  1. 1. Implementing GraphQL API in Elixir By Victor Deryagin, Wise Engineering
  2. 2. What? ● GraphQL ● Our team’s experience of using Elixir for implementing TpT Graph API ● Other random thoughts and opinions . It will be fun
  3. 3. 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
  4. 4. Query/result example (GitHub API)
  5. 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. 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. 7. Teachers Pay Teachers ● open since 2006 ● 5m+ active users (⅔ of teachers in US) ● 3m+ products ● ~60 engineers
  8. 8. TpT infrastructure ● AWS ● Terraform/Kubernetes/Docker ● MySQL, Redis, Memcached ● Hundreds of nodes
  9. 9. TpT Graph API ● Almost 2 years old ● 2k rps ● Handles significant proportion of work ● Almost all new backend feature development happens here
  10. 10. Server stack ● Elixir ● Phoenix (mostly its router) ● Absinthe ● Ecto, connected to legacy data stores
  11. 11. Client stack ● React ● Apollo client (js & iOS) ● Redux
  12. 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. 13. Introspection Enables powerful tools, makes one think carefully about what is exposed in the schema
  14. 14. Separation of schemas It’s easy to prevent field from being resolved, but we need a different approach to completely hide its existence
  15. 15. Structuring the schema Nested objects allow to contain complexity
  16. 16. Access control for free You only have to worry about limiting access to one field, everything under it is going to be protected
  17. 17. Batching ● Absinthe.Middleware.Batch ● DataLoader: https://github.com/absinthe-graphql/dataloader
  18. 18. 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
  19. 19. 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
  20. 20. 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
  21. 21. 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
  22. 22. 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
  23. 23. Distributed request tracing
  24. 24. 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
  25. 25. 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
  26. 26. 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
  27. 27. 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
  28. 28. Thanks! Victor Deryagin vderyagin@gmail.com https://wise-engineering.com
  29. 29. Questions?

×