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

You ain't gonna need to write a GenServer

You ain't gonna need to write a GenServer

GenServers plays a central role in Elixir OTP applications. However, when you overuse it, it can become an anti-pattern and introduce bottlenecks in your system.

In this talk you'll learn:

* What's a GenServer
* When GenServer can harm
* GenServer FOMO (fear of missing out)
* How Elixir ecosystem get you covered

After this talk, you'll understand how putting a GenServer in the wrong place can slowdown in your entire system. You'll understand how the Elixir frameworks and libraries enable you to have reliable concurrency applications. You'll feel no shame of being an Elixir developer and never had to write yourself a GenServer.

Ulisses Almeida

May 25, 2019
Tweet

More Decks by Ulisses Almeida

Other Decks in Programming

Transcript

  1. You ain't gonna need to
    write a GenServer
    by Ulisses Almeida

    View full-size slide

  2. Summary
    ■ What is GenServer?
    ■ How can you harm your app by putting
    GenServer in the wrong place?
    ■ Why do people think that they need a
    GenServer all the time?
    ■ Considerations before writing a GenServer

    View full-size slide

  3. I’m Ulisses Almeida
    ■ Elixir Developer at The
    Coingaming Group
    ■ Brazilian !
    ■ @ulissesalmeida

    View full-size slide

  4. Learn Functional Programming with Elixir
    ■ 20% off with
    Elixir_Brazil_2019
    promo code
    ■ 3 e-books giveaways

    View full-size slide

  5. Who 

    We Are
    The Coingaming Group are the
    crypto gaming pioneers who
    operate the world’s leading bitcoin
    gaming and betting brands.
    https://coingaming.io/

    View full-size slide

  6. Why Tallinn? "
    ★ Low renting costs
    ★ Free transportation for
    residents
    ★ E-estonia
    ★ Safe
    ★ Low taxes
    ★ Accessible travels
    ๏ Cold and Dark ☃
    ๏ Estonian is the first
    language "
    ๏ Russian is the second
    language %
    ๏ Eastern/nordic culture
    is different

    View full-size slide

  7. Ok, GenServers
    A quick recap

    View full-size slide

  8. https://twitter.com/ulissesalmeida/status/1125455706470088704

    View full-size slide

  9. GenServer
    ■ Useful for: Client-Server
    relation
    ■ Keep state
    ■ Execute code
    asynchronously
    (handle_cast)
    ■ Synchronously too
    (handle_call)
    ■ Provide tracing and error
    reporting features
    ■ Can be supervised
    A process with a
    powerful set of
    features

    View full-size slide

  10. Shades of a GenServer
    ■ Agent
    ■ Task
    ■ Task.Supervisor
    ■ Supervisor
    ■ DynamicSupervisor

    View full-size slide

  11. CalculatorServer
    Baby
    1+1?
    1.
    2.
    3.
    From: Baby

    1+1?
    4.
    1+1=2
    5.

    View full-size slide

  12. CalculatorServer
    Baby
    7.
    6.
    From: 

    MyCalcGenServer

    2
    8.

    View full-size slide

  13. Live demo
    “…maybe I should have
    recorded a video”

    View full-size slide

  14. hahahahah GenServer

    bottleneck

    omg what I have 

    done!?

    View full-size slide

  15. Holy %#@!
    ~ 200 times slower

    ~ 10 times more
    memory
    120km/h
    1.6km/h
    ~75 times slower
    10 times bigger

    View full-size slide

  16. What happened!?

    View full-size slide

  17. CalculatorServer
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAA

    View full-size slide

  18. Without GenServer…

    View full-size slide

  19. CalculatorServer

    View full-size slide

  20. CalculatorServer




    ta pegando fogo bicho!
    !

    View full-size slide

  21. Why people want it so
    much?
    Can we play just with
    functions?

    View full-size slide

  22. Erlang OTP
    ■ Process hierarchy
    ■ Restarting strategies
    ■ Concurrency
    ■ GenServer plays the
    central role

    View full-size slide

  23. wait, you said
    concurrency…

    View full-size slide

  24. GenServer checklist
    ■ Model state accessed by multiple
    processes
    ■ Run multiple tasks concurrently
    ■ Communicate between servers
    ■ Gracefully handle clean startup and exit
    concerns
    https://pragprog.com/book/tvmelixir/adopting-elixir

    View full-size slide

  25. CalculatorServer checklist
    ❌Model state accessed by multiple
    processes
    ❌Run multiple tasks concurrently
    ❌Communicate between servers
    ❌Gracefully handle clean startup and exit
    concerns
    https://pragprog.com/book/tvmelixir/adopting-elixir

    View full-size slide

  26. CalculatorServer has no
    reason to be a GenServer
    A GenServer must
    never be used for
    code organization
    purposes
    https://hexdocs.pm/elixir/GenServer.html
    GenServer to organize 

    domain, business

    contexts
    GenServer to model 

    runtime properties

    of your system

    View full-size slide

  27. Fear of missing
    out?
    Am I a proper Elixir
    developer If I'm not
    doing GenServers?

    View full-size slide

  28. I have been working with Elixir for ~3 years
    ■ I never wrote a production GenServer
    ■ I wrote GenServers only in recruitment
    processes and for fun
    ■ I deleted some unnecessary production
    GenServers
    ■ I know excellent developers that never
    wrote one

    View full-size slide

  29. Elixir developers, no
    shame in never had to
    create a GenServer.

    View full-size slide

  30. Ecosystem got you
    covered
    Or… things that you should consider
    before writing a GenServer

    View full-size slide

  31. Let's think about a typical
    web application

    View full-size slide

  32. Phoenix
    Elixir
    Database
    Legacy
    Legacy of the Legacy
    Users

    View full-size slide

  33. Users -> App checklist
    ✔ We need to handle multiple users
    connections concurrently
    ✔ Other processes might send messages to
    that connection
    ✔ We have to handle connections openings
    and closings gracefully.

    View full-size slide

  34. However…
    ■ Each user’s request
    has a process that runs
    concurrently
    ■ You can focus on the
    functional part
    ■ (functional part?
    functional
    programming )
    Phoenix and
    Cowboy handles
    that for you

    View full-size slide

  35. App &
    Database

    View full-size slide

  36. App & Database checklist
    ✔Databases are an external service
    communication
    ✔We have to provide a limited number of
    connections to a lot of processes
    ✔These connections have to run
    ✔We need to handle connection openings
    and closings gracefully

    View full-size slide

  37. GenServers!!!!

    View full-size slide

  38. However…
    ■ Ecto supports a pool of
    connections
    ■ Ecto handle that
    concurrently
    ■ Work here is also done
    ■ You can focus on the
    business
    Ecto handles that
    for you

    View full-size slide

  39. App &Other
    Services

    View full-size slide

  40. App & Other Services checklist
    ✔ Usually, we communicate through a network
    ✔ We might need to offer a pool as a backpressure
    mechanism to not bring down weak services
    ✔ These pools have to run multiple requests
    concurrently
    ✔ Gracefully handle connections opening and
    closings

    View full-size slide

  41. GenSeerveerss!!!

    View full-size slide

  42. However…
    ■ You can start simple,
    for example, no pool
    ■ Watch out for big
    timeouts
    ■ Circuit breakers can
    help you out
    ■ Choose the libraries,
    and you can focus on
    features
    Hackney and other
    libraries handles
    that for you

    View full-size slide

  43. NoSQL storage

    View full-size slide

  44. Not everything is stored in SQL databases
    ■ Examples: caching,
    session, users
    presence
    ■ Transient or Persistent?
    ■ How big will it be?
    ■ Write vs Read
    ✔ This data will be
    accessible by multiple
    processes

    View full-size slide

  45. GenSeeerveerS!!!!!

    View full-size slide

  46. WITH ETS!!!!!!!

    View full-size slide

  47. Phoenix
    Elixir
    Elixir
    ETS table
    Phoenix
    Elixir
    ETS table
    Phoenix
    Elixir
    ETS table
    User

    View full-size slide

  48. However…
    ■ A better abstraction reveals
    intention, for example,
    Cachex vs GenServer + ETS
    ■ How does your deploy
    work?
    ■ Shutdown and booting the
    app will lose GenServer/
    ETS data
    ■ Redis for the rescue
    ■ Discuss the right tool for
    the job, compare the
    tradeoffs
    You might want to
    use a specific
    abstraction.

    View full-size slide

  49. Serializable
    operations

    View full-size slide

  50. Serializable
    operations
    Some resources
    can’t be changed at
    same time
    1
    1
    5
    I want to withdraw 2
    I want to withdraw 6
    Company Wallet
    ✔ Manage state accessed
    by multiple processes

    View full-size slide

  51. …GenServer?

    View full-size slide

  52. However…
    ■ You would need an
    Erlang cluster to run a
    global GenServer
    ■ What happens with
    network partition?
    ■ Use your database
    power
    ■ Transactions or locks in
    the database
    ■ Discuss with your team,
    compare the tradeoffs
    You environment
    might not allow.
    a.k.a Heroku

    View full-size slide

  53. Background
    tasks

    View full-size slide

  54. Tasks outside of a request/response cycle
    ■ Welcome e-mail
    ■ Push notifications
    ■ Scheduled tasks
    ✔ We need to spawn or
    schedule these
    background tasks
    ✔ We need to run the
    background tasks
    concurrently

    View full-size slide

  55. Dynamic Supervisors 

    & Task!!!

    View full-size slide

  56. However…
    ■ GenServers aren’t
    persistent
    ■ Shutting downs might
    lose data
    ■ RabbitMQ has persistent
    queues
    ■ Libraries that use Redis
    to store the jobs and
    their arguments
    ■ Discuss with your team,
    compare the tradeoffs
    How to handle the
    failures? Do you
    need some
    persistence?

    View full-size slide

  57. We covered a lot 

    of considerations before 

    “let's write a GenServer” decision
    And they are still not
    over

    View full-size slide

  58. GenServers are
    fundamental

    View full-size slide

  59. Elixir frameworks and
    libraries cover most of
    the use cases that you
    would need to write one

    View full-size slide

  60. But it doesn’t mean
    you should not learn
    about GenServer

    View full-size slide

  61. You need to know
    GenServer to tune
    their configurations

    View full-size slide

  62. When stuff goes
    wrong, you’ll need
    to debug and fix it.

    View full-size slide

  63. You won’t might need
    to write a GenServer
    95% of time…

    View full-size slide

  64. But that 5%…

    View full-size slide

  65. Then, keep
    learning!

    View full-size slide

  66. Putting a GenServer in
    the wrong place brings
    more harm than good

    View full-size slide

  67. It’s good to compare
    and to discuss the
    tradeoffs with your
    team.

    View full-size slide

  68. There’s no shame
    in never need to
    write a GenServer

    View full-size slide

  69. References
    ■ Adopting Elixir - https://pragprog.com/book/tvmelixir/adopting-
    elixir
    ■ Spawn or not spawn - https://www.theerlangelist.com/article/
    spawn_or_not
    ■ You may not need a GenServer - https://pragtob.wordpress.com/
    2019/04/24/you-may-not-need-genservers-and-supervision-trees
    ■ GenServer (Elixir Docs) - https://hexdocs.pm/elixir/GenServer.html
    ■ Elixir discussion forum - https://elixirforum.com/t/you-may-not-
    need-genservers-and-supervision-trees/12947

    View full-size slide