Read this Article if you want to learn Elixir with GenServer.
Tags: elixir, liveview, phoenix, programming
Published: 2022-08-02 17:37:00

# Greeting

Hello #devElixir!!! Welcome to #FullStackElxpro

Here we discuss strategies and tips for your Elixir learning journey, from scratch to a hero Elixir developer.


I am Gustavo, and today&#39;s theme is **GenServer**.

_ps: You can follow the Article with **a [VIDEO](https://youtu.be/uBBPdfvHLZ0)**_

**Do you want to learn Elixir in three months? https://elxpro.com/sell**

_Want to learn more about Elixir on a Telegram channel?_

https://elxpro.com/subscribe-elxcrew

# What is a GenServer?

[GenServer](https://hexdocs.pm/elixir/GenServer.html) is a process like any other Elixir process (_Tasks, Spawn, Agents_). It can be used to manage state and execute code asynchronously and includes some handy functionality around tracing and error reporting.

And for me, as a Liveview evangelist is one of the best ways to learn what you have behind the LiveView Apps, providing a better way to organize, think and isolate pieces of code.

Before we move forward, I think it is essential to read [When Not Use GenServer](https://hexdocs.pm/elixir/GenServer.html#module-when-not-to-use-a-genserver). Because one of the biggest mistakes you can make is using GenServer for Everything, which is unnecessary.

# What is the difference between GenServer, Tasks, and Agents?

Before you keep reading this article, I highly recommend watching the video about Elixir&#39;s processes.

https://youtu.be/em4QECkQx4s

**GenServer** : The GenServer behaviour abstracts the common client-server interaction. Developers are only required to implement the callbacks and functionality they are interested in.

[**Tasks**](https://hexdocs.pm/elixir/Task.html): Tasks are processes meant to execute one particular action throughout their lifetime, often with little or no communication with other processes. The most common use case for tasks is to convert sequential code into concurrent code by computing a value asynchronously.

[**Agents**](https://hexdocs.pm/elixir/Agent.html): Agents are a simple abstraction around state.

# Why is GenServer Important?

I have seen developers who start their career as Elixir developers but don&#39;t understand the basic concepts of how Elixir works.

Elixir is not a normal programming language. I mean that because Frontend Developers usually come to Elixir from React, Angular, and Vue, all of which use JavaScript and oriented programming languages. And daily, they face difficulties understanding what is behind LiveView, how to split components, and thinking in **single responsibilities principles.**

They don&#39;t understand it because of two simple things. Behind Elixir, there are processes, and LiveView is very similar to a GenServer.

# What is the best moment to use GenServer?

**Handle Sync and Async Calls:** As we discussed, the main purpose of a GenServer is not to Code Organization but as a way to keep the state and manipulate it easily. Example **Shopping Cart**

**System Messages:** You can see some examples when you create ways to use _spawn, send and receive__ **. As** _ I mentioned, I recorded a video explaining how the process works, and one of the examples is a simulation of how to access the database and execute a query.

**Monitoring Events:** Imagine that you have a company monitoring company stocks every second. The stocks&#39; assets rise and fall every second.

# Where to start?

## Callbacks

- init/1 (required) - invoked when the server is started and sets the initial state
- handle_cast/2 - invoked when GenServer.cast/2 is called to handle messages asynchronously
- handle\_call/3 - invoked when GenServer.call/3 is called to handle messages synchronously
  - call/3 will block until a reply is received (unless the call times out or nodes are disconnected)
- handle\_info/2 - invoked to handle all other messages (i.e., outside of those triggered by GenServer.call/3 and GenServer.cast/2, and [&quot;system&quot; messages](https://erlang.org/doc/design_principles/spec_proc.html#msg))
  - g., messages/events handled internally within the GenServer
- terminate/2 - invoked when the GenServer is about to exit

## Init

Before we talk about Init, we must talk about **start_link **together.

**start_link**: when it is called, the new process created will call **init**, and **init** will start the state, which is an empty map, and the parent of **ShoppingCart **is the IEX terminal.

Take a look at the code.

```
defmodule ShoppingCart do
  use GenServer

  def start_link([name, state]) do
    IO.inspect(state, label: "start_link")
    GenServer.start_link(__MODULE__, state, name: name)
  end

  def init(state) do
    IO.inspect state, label: "init"
    {:ok, state}
  end
end
```

```
iex(1)> ShoppingCart.start_link [:elxpro_cart, []]
start_link: []
init: []
{:ok, #PID<0.161.0>}
iex(2)> Process.whereis :elxpro_cart
#PID<0.161.0>
iex(3)> self   
#PID<0.159.0>
iex(4)> :observer.start

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gvdmcnweflbuudvfoxog.png)






## HandleCast


----------

Invoked when GenServer.cast/2 is called to handle messages asynchronously

In our example, imagine that you need to add a new product to your cart but don't care how many products you have there. You only want to add it is a perfect example of how to call **handle_cast.**


```
  def handle_cast({:add, product}, state) do
    state = state ++ [product]
    {:noreply, state}
  end
```

```
iex(1)> ShoppingCart.start_link [:cart_1, []]
start_link: []
init: []
{:ok, #PID<0.151.0>}

iex(2)> GenServer.cast :cart_1, {:add, %{name: "Pumpkin", price: 10}}

iex(3)> "0.151.0" |> pid |> :sys.get_state
```




## HandleCall
----------

The **handle_call**/3 callback is invoked when GenServer.call/3 is called to handle synchronous messages. The main params are **function_pattern_mathing**, **_from,** **state**.

**function_pattern_mathing: **a Way to identify how to call the function

**_from: **most of the time is the process_id that calls the function, and most of the time is useful 

**state: **actual component state.

And the most common return is** {:reply, response, state}**

**Reply: **indicates that those who called the process will receive a message result.

**Response:** message to return for who called the process.

**State: **update process state.

Check the example, Bellow:





```
  def handle_call(:apply_discount, _from, state) do
    state = Enum.map(state, &%{&1 | price: &1.price - 1})
    products = Enum.map(state, &(&1.name <> " "))
    {:reply, "Discount applied to: #{products}", state}
  end
```

```
iex(1)> ShoppingCart.start_link [:cart_1, []]
start_link: []
init: []
{:ok, #PID<0.161.0>}


iex(2)>  GenServer.cast :cart_1, {:add, %{name: "Pumpkin", price: 10}}

iex(3)>   GenServer.cast :cart_1, {:add, %{name: "Gatorade", price: 20}}


iex(6)>  GenServer.call :cart_1, :apply_discount            
Result: "Discount applied to: Pumpkin Gatorade "

State: 
iex(7)>   pid = "0.161.0" |> pid |> :sys.get_state
[%{name: "Pumpkin", price: 8}, %{name: "Gatorade", price: 18}]
```


----------

## HandleInfo

The handle_info/2 callback is invoked to handle all other messages (i.e., outside of those triggered by GenServer.call/3 and GenServer.cast/2)




```
  def handle_info(:increase_price, state) do
    state = Enum.map(state, &%{&1 | price: &1.price + 1})
    {:noreply, state}
  end
```


```
iex(1)>  ShoppingCart.start_link [:cart_1, []]
iex(2)> GenServer.cast :cart_1, {:add, %{name: "Pumpkin", price: 10}}
iex(3)> pid = pid("0.161.0")                

iex(4)> :sys.get_state(pid)
[%{name: "Pumpkin", price: 10}]

iex(5)> send pid, :increase_price
iex(6)> :sys.get_state(pid)      
[%{name: "Pumpkin", price: 11}]
```


Code:

```
defmodule ShoppingCart do
  use GenServer

  def start_link([name, state]) do
    IO.inspect(state, label: "start_link")
    GenServer.start_link(__MODULE__, state, name: name)
  end

  def init(state) do
    IO.inspect(state, label: "init")
    {:ok, state}
  end

  def handle_cast({:add, product}, state) do
    state = state ++ [product]
    {:noreply, state}
  end

  def handle_call(:apply_discount, _from, state) do
    state = Enum.map(state, &%{&1 | price: &1.price - 1})
    products = Enum.map(state, &(&1.name <> " "))
    {:reply, "Discount applied to: #{products}", state}
  end

  def handle_info(:increase_price, state) do
    state = Enum.map(state, &%{&1 | price: &1.price + 1})
    {:noreply, state}
  end
end
```


#THE END.

The main goal of this Article is to help you understand how easy it is GenServer and after couple examples, you can possibly create simpler LiveView Pages and Elixir Codes



Social networks:

- Gustavo Oliveira - https://www.linkedin.com/in/gustavo-oliveira-642b23aa/
- Elxpro Linkedin - https://www.linkedin.com/company/36977430
- Twitter - https://twitter.com/elx_pro
- ElxproBr - https://www.youtube.com/channel/UCl_BBK2sXZzQy_3ziNU7-XA
- Elxpro - https://www.youtube.com/channel/UCLzHBFuE6oxPdP6t9iqpGpQ