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.

50e713934ed341675bf1fa73127ec260?s=128

Ulisses Almeida

May 25, 2019
Tweet

Transcript

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

    Almeida
  2. None
  3. None
  4. 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
  5. I’m Ulisses Almeida ▪ Elixir Developer at The Coingaming Group

    ▪ Brazilian ! ▪ @ulissesalmeida
  6. Learn Functional Programming with Elixir ▪ 20% off with Elixir_Brazil_2019

    promo code ▪ 3 e-books giveaways
  7. 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/
  8. None
  9. None
  10. None
  11. 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
  12. Ok, GenServers A quick recap

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

  14. None
  15. None
  16. None
  17. None
  18. 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
  19. Shades of a GenServer ▪ Agent ▪ Task ▪ Task.Supervisor

    ▪ Supervisor ▪ DynamicSupervisor
  20. CalculatorServer Baby 1+1? 1. 2. 3. From: Baby
 1+1? 4.

    1+1=2 5.
  21. CalculatorServer Baby 7. 6. From: 
 MyCalcGenServer
 2 8.

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

  23. None
  24. None
  25. None
  26. None
  27. None
  28. None
  29. None
  30. None
  31. None
  32. UÉ!?

  33. hahahahah GenServer
 bottleneck
 omg what I have 
 done!?

  34. Holy %#@! ~ 200 times slower
 ~ 10 times more

    memory 120km/h 1.6km/h ~75 times slower 10 times bigger
  35. What happened!?

  36. CalculatorServer AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA

  37. Without GenServer…

  38. CalculatorServer

  39. CalculatorServer ☠ ta pegando fogo bicho! !

  40. Why people want it so much? Can we play just

    with functions?
  41. Erlang OTP ▪ Process hierarchy ▪ Restarting strategies ▪ Concurrency

    ▪ GenServer plays the central role
  42. wait, you said concurrency…

  43. 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
  44. 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
  45. 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
  46. Fear of missing out? Am I a proper Elixir developer

    If I'm not doing GenServers?
  47. 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
  48. Elixir developers, no shame in never had to create a

    GenServer.
  49. Ecosystem got you covered Or… things that you should consider

    before writing a GenServer
  50. Let's think about a typical web application

  51. Phoenix Elixir Database Legacy Legacy of the Legacy Users

  52. None
  53. Users & App

  54. 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.
  55. GenServers!

  56. 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
  57. App & Database

  58. 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
  59. GenServers!!!!

  60. 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
  61. App &Other Services

  62. 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
  63. GenSeerveerss!!!

  64. 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
  65. NoSQL storage

  66. 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
  67. GenSeeerveerS!!!!!

  68. WITH ETS!!!!!!!

  69. Phoenix Elixir Elixir ETS table Phoenix Elixir ETS table Phoenix

    Elixir ETS table User
  70. 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.
  71. Serializable operations

  72. 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
  73. …GenServer?

  74. 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
  75. Background tasks

  76. 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
  77. Dynamic Supervisors 
 & Task!!!

  78. 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?
  79. We covered a lot 
 of considerations before 
 “let's

    write a GenServer” decision And they are still not over
  80. GenServers are fundamental

  81. Elixir frameworks and libraries cover most of the use cases

    that you would need to write one
  82. But it doesn’t mean you should not learn about GenServer

  83. You need to know GenServer to tune their configurations

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

    it.
  85. You won’t might need to write a GenServer 95% of

    time…
  86. But that 5%…

  87. Then, keep learning!

  88. Remember

  89. Putting a GenServer in the wrong place brings more harm

    than good
  90. It’s good to compare and to discuss the tradeoffs with

    your team.
  91. There’s no shame in never need to write a GenServer

  92. Thank you

  93. 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