Elixir GenServer?
Tags: elixir, phoenix, erlang, genserver
Published: 2020-10-07 02:55:52

Primeiramente, oi 👋 me chamo Willian, sou desenvolvedor e pretendo usar esse espaço para compartilhar o pouco que aprendi durante esses últimos anos trabalhando com TI.   Se você é pessoa desenvolvedora back-end e/ou está sempre procurando atualizações, novas tecnologias ou novos conhecimentos, esse texto é para você!


Bom, vem comigo.

![Come on!!!](https://media.giphy.com/media/LoCDk7fecj2dwCtSB3/giphy.gif)


# Elixir

Se você ainda não conhece a linguagem de programação Elixir, vou deixar alguns links abaixo que considero como sendo os de maior influência para te dar uma leve noção de sintaxe e semântica, porém nada muito profundo, para não te sobrecarregar. :smile:  

Links:
https://elixir-lang.org/
https://elixirschool.com/pt


Além disso, pretendo postar mais conteúdos sobre e garantir que seja possível acompanhar essa tecnologia, e entender como ela pode funcionar (ou não) para você!


# GenServer

## O que seria isso?  

Ele é um dos módulos que compõem o pacote [OTP (Erlang/BEAM)](https://en.wikipedia.org/wiki/Open_Telecom_Platform). É possível acessar ele a partir do Elixir graças a [interoperabilidade](https://elixir-lang.org/getting-started/erlang-libraries.html) que a linguagem oferece.   

Diz-se que o GenServer é um tipo de processo, assim como os demais processos que podem ser gerados no Elixir (ex: _[Agent](https://hexdocs.pm/elixir/Agent.html)_, _[Task](https://hexdocs.pm/elixir/Task.html)_). O seu diferencial é que os processos que são criados a partir de sua implementação possuem um estado interno; em outras palavras, você pode criar um processo que roda como um servidor à parte, de forma assíncrona, sem interferir na sua aplicação principal, e esse processo terá um estado interno que poderá ser alterado da forma que for mais adequado para suas necessidades.

## Ciclo de vida

O ciclo de vida do seu GenServer tende a funcionar da seguinte maneira: inicia -> loop(chama uma função -> gera um novo estado).

Ex:
Suponhamos que você tenha utilizado o GenServer para implementar uma pilha, seria mais ou menos assim:

![diagrama sobre o uso do GenServer](https://dev-to-uploads.s3.amazonaws.com/i/ne0h89af65dtuydkyits.png)

A sua aplicação inicia essa pilha chamando **Stack.start()** (você está iniciando o seu processo).

Você pode adicionar elementos ou remover elementos utilizando:
```
stack.push(value) # value = valor que você deseja adicionar.
stack.pop() # retorna o valor que está no topo da pilha.
```

Os métodos `push/1` e `pop/0` se encaixam no `loop` citado acima, onde você está chamando uma função e atualizando o estado interno do seu **GenServer**.

⚠️ Lembrando que essa pilha irá executar o `push/1` de forma assíncrona por ser implementada usando o método `handle_cast`.


## Exemplo implementação de pilha

Seguindo no exemplo do tópico anterior, se estivesse implementando uma pilha, você iria neste caminho:
```
defmodule Stack do
  use GenServer

  # {...} Outras implementações como init, start_link, etc...

  def handle_call(:pop, _from, [value | state]), do: {:reply, value, state}
  def handle_call(:pop, _from, []), do: {:reply, nil []}

  def handle_cast({:push, value}, state), do: {:no_reply, [value | state]}

  def push(value), do: GenServer.cast(__MODULE__, {:push, value})
  def pop(), do: GenServer.call(__MODULE__, :pop)
end

```  


E isso rodaria mais ou menos assim: 

![exemplo executando pilha, formato GIF](https://dev-to-uploads.s3.amazonaws.com/i/dtukbkb1npp4yyt637z0.gif)

## Curiosidades  

O [Discord](https://discord.com/) atualmente utiliza Elixir e resolve alguns de seus problemas técnicos utilizando GenServer. Um bom exemplo disso é a implementação de semaphores que foi feito para tratar o gerenciamento dos processos, link: https://github.com/discord/semaphore.

Além disso, existem libs do próprio ecossistema do Elixir que utilizam GenServer, um bom exemplo disso seria a própria lib do [kafka_ex](https://github.com/kafkaex), que conecta a sua aplicação ao seu serviço [Apache Kafka](http://kafka.apache.org/).


## Conclusão

O GenServer é muito utilizado no dia-a-dia de um desenvolvedor Elixir, as vezes até mesmo de forma inconsciente (em libs, frameworks, etc). Por isto, é sempre bom conhecer e saber que ele existe e como ele funciona por baixo dos panos.

Deixarei aqui um repositório com algumas implementações básicas de estruturas de dados:
{% github WLSF/data_structures_ex %}


Por hoje é só, até a próxima... 👋