Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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/

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Ok, GenServers A quick recap

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

CalculatorServer Baby 1+1? 1. 2. 3. From: Baby
 1+1? 4. 1+1=2 5.

Slide 21

Slide 21 text

CalculatorServer Baby 7. 6. From: 
 MyCalcGenServer
 2 8.

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

UÉ!?

Slide 33

Slide 33 text

hahahahah GenServer
 bottleneck
 omg what I have 
 done!?

Slide 34

Slide 34 text

Holy %#@! ~ 200 times slower
 ~ 10 times more memory 120km/h 1.6km/h ~75 times slower 10 times bigger

Slide 35

Slide 35 text

What happened!?

Slide 36

Slide 36 text

CalculatorServer AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA

Slide 37

Slide 37 text

Without GenServer…

Slide 38

Slide 38 text

CalculatorServer

Slide 39

Slide 39 text

CalculatorServer ☠ ta pegando fogo bicho! !

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

wait, you said concurrency…

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

Let's think about a typical web application

Slide 51

Slide 51 text

Phoenix Elixir Database Legacy Legacy of the Legacy Users

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

Users & App

Slide 54

Slide 54 text

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.

Slide 55

Slide 55 text

GenServers!

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

App & Database

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

GenServers!!!!

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

App &Other Services

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

GenSeerveerss!!!

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

NoSQL storage

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

GenSeeerveerS!!!!!

Slide 68

Slide 68 text

WITH ETS!!!!!!!

Slide 69

Slide 69 text

Phoenix Elixir Elixir ETS table Phoenix Elixir ETS table Phoenix Elixir ETS table User

Slide 70

Slide 70 text

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.

Slide 71

Slide 71 text

Serializable operations

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

…GenServer?

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

Background tasks

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

Dynamic Supervisors 
 & Task!!!

Slide 78

Slide 78 text

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?

Slide 79

Slide 79 text

We covered a lot 
 of considerations before 
 “let's write a GenServer” decision And they are still not over

Slide 80

Slide 80 text

GenServers are fundamental

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

You need to know GenServer to tune their configurations

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

But that 5%…

Slide 87

Slide 87 text

Then, keep learning!

Slide 88

Slide 88 text

Remember

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

Thank you

Slide 93

Slide 93 text

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