Elixir GenServer Explained to Redux Developers
Tags: elixir, redux, javascript, genserver
Published: 2017-12-19 20:30:31

---
title: "Elixir GenServer Explained to Redux Developers"
published: true
description: "GenServer is the cornerstone of a lot of Elixir distributed apps. If know Redux, you'll easily understand its strengths"
canonical_url: https://marmelab.com/blog/2017/10/04/elixir-genserver-explained-to-redux-developers.html
cover_image: https://marmelab.com/images/blog/201709_genserver_banner.png
tags: elixir,redux,js,genserver
---

Note: This post was originally posted on [marmelab.com](https://marmelab.com/blog/2017/10/04/elixir-genserver-explained-to-redux-developers.html).

Although very young, [the Elixir language](https://elixir-lang.org/) has gained a lot of popularity since its creation. Whereas based upon an ancestral language / platform called [Erlang](https://en.wikipedia.org/wiki/Erlang_(programming_language)) [BEAM](https://stackoverflow.com/questions/16779162/what-kind-of-virtual-machine-is-beam-the-erlang-vm?answertab=votes#tab-top), Elixir provides strong functional, concurrent and distributed capabilities. Its feel modern and fun. That's why I just could not resist to play with it.

In this post, I'll give the keys that helped me understand GenServer, the cornerstone of a lot of Elixir distributed applications / systems.

## The GenServer Swiss Knife

Like any other language built on top of the Erlang VM, Elixir relies on lightweight and isolated threads (usually called [processes](https://elixir-lang.org/getting-started/processes.html)), and messages passed between these threads. The key benefits of this mechanism are primarily fault-tolerance, distributivity and scalability.

The [gen_server](http://erlang.org/doc/design_principles/gen_server_concepts.html) (for "Generic Server") is a standard module included in the underlying [Erlang OTP](http://learnyousomeerlang.com/what-is-otp) (Open Telecommunications Platform). It offers abstractions to build a basic client <-> server system with a common shared resource (state). It was used in a lot of Open Source projects in the Elixir community.

GenServer usually acts as a central registry with its own state, on which we can perform (a)synchronous actions via message passing. In the web dev world, it can be roughly compared to an asynchronous [Redux](http://redux.js.org/) store.

So how does it compare with Redux? In the example below, I'll create a simple registry of quotes. I'll use both GenServer and Redux to show what they have in common.

## The Elixir Version

Here is how to implement a registry of quotes with GenServer:

```elixir
# quotes_list.ex

defmodule QuotesList do
    use GenServer

    # Client API

    def start_link do
        GenServer.start_link(__MODULE__, :ok, [])
    end

    def read(pid) do
        GenServer.call(pid, {:read})
    end

    def add(pid, quote) do
        GenServer.cast(pid, {:add, quote})
    end

    # Server Callbacks

    def init(:ok) do
        {:ok, []}
    end

    def handle_call({:read}, from, list) do
        {:reply, list, list}
    end

    def handle_cast({:add, quote}, list) do
        {:noreply, list ++ [quote]}
    end
end
```

In this snippet, I define an Elixir module called `QuotesList`. Since `GenServer` comes from an underlying Erlang library, it was provided through an Elixir Bridge with a kind of "mixin" (thanks to the ["use"](https://elixir-lang.org/getting-started/alias-require-and-import.html#use) macro).

In the Elixir world, `start_link` is the common method name for starting a process which is attached to the current [supervision tree](https://elixir-lang.org/getting-started/mix-otp/supervisor-and-application.html). The third parameter of this method represents the [initial state](http://redux.js.org/docs/recipes/reducers/InitializingState.html) (an empty array) of our QuotesList module.

The **Client API** section can be defined as the public interface of our module. We can call `read`, `add`, ... from the outside to manipulate or access our store at our convenience.

On the other side, the **Server Callbacks** section is responsible for the inner working state manipulation of the GenServer. It responds respectively to the different calls / casts made in the Client API section, thanks to the strong [pattern matching](https://elixir-lang.org/getting-started/pattern-matching.html) capabilities of Elixir. In the next chapter, I'll cover this section in a deeper way.

To conclude this part about the Elixir implementation, here is an example of GenServer usage for our `QuotesList` module.

```elixir
# another_module.ex

# Start the quote server
{:ok, pid} = QuotesList.start_link

# Adding some items
QuotesList.add(pid, "All that glitters is not gold.")
QuotesList.add(pid, "Elementary, my dear Watson.")
QuotesList.add(pid, "Houston, we have a problem.")

# Read the quotes back
QuotesList.read(pid)
```

## The Redux Version

On the Redux side, here is the equivalent of the preceding example in [ES6](https://en.wikipedia.org/wiki/ECMAScript#6th_Edition_-_ECMAScript_2015). 

```js
// quoteListStore.js

import { createStore } from 'redux'

function quoteListReducer(state = [], action) {
    switch (action.type) {
    case 'add':
        return [ ...state, action.quote ];
    default:
        return state;
    }
}

return createStore(quoteListReducer)
```

Contrary to the Elixir implementation, there's no need to create a "read" method in Redux. We can access the state value directly with [getState](http://redux.js.org/docs/api/Store.html#getState) on the store. 

Furthermore, the initial state is defined directly into the default value of the [reducer](http://redux.js.org/docs/basics/Reducers.html) and not in the [createStore](http://redux.js.org/docs/api/createStore.html) initializer.

Elixir relies on [atom](https://elixir-lang.org/getting-started/basic-types.html#atoms) tags to bring matching capabilities to our handlers. In EcmasScript, we use a `type` attribute to match the right case of the reducer switch.

In Elixir, it's necessary to access data by message passing from another process. It's not required in the EcmaScript [EventLoop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop) which is mono-threaded.

And here is how to use the Redux registry in ES: 

```js
// index.js

import quoteListStore from './quoteListStore.js';

const addQuote = item => ({ type: 'add', quote });

quoteListStore.dispatch(addQuote('All that glitters is not gold.'));
quoteListStore.dispatch(addQuote('Elementary, my dear Watson.'));
quoteListStore.dispatch(addQuote('Houston, we have a problem.'));

quoteListStore.getState();
```

## Call, Cast & Info Callbacks

If you've never encountered GenServer before, you've certainly asked yourself about the meaning of `cast` and `call`. These "verbs" corresponds to two different types of actions which can be triggered. 

The `cast` action consists of an asynchronous action on the store, without any expectation on the result. It means that the action is queued and ready to be processed by corresponding GenServer `handle_cast` handler ASAP. It's similar to the famous [dispatch](http://redux.js.org/docs/api/Store.html#dispatch) method in Redux.

On the other side, the `call` action consists of a synchronous action on the store. The calling process is paused until the action is processed by corresponding GenServer `handle_call` handler. It's most often used to access the data.

Another `info` action exists, but is not usually used. This action is triggered when an incoming message comes from an unknow source / process (not the Client API section). The corresponding `handle_info` can be compared to some kind of "catchAll" handler (`default` case in a Redux reducer `switch / case`).

## Conclusion

If I had to compare Redux and Elixir GenServer, I would say that:

- GenServer != Redux because of the nature of each running platform.<br/>Erlang BEAM / Elixir is distributed, EcmaScript is not.
- GenServer offers kind of [RPC](https://en.wikipedia.org/wiki/Remote_procedure_call) capabilities through calls. Redux doesn't.
- When the only purpose of Redux is to manipulate the "state", it's not the case of GenServer.
- Redux reducer logic is centralized, GenServer logic is split in multiple `handle_*` methods.

You may also be interested by the following related links to go further into  Elixir and GenServer.

* [https://hexdocs.pm/elixir/GenServer.html](https://hexdocs.pm/elixir/GenServer.html)
* [http://culttt.com/2016/08/24/understanding-genserver-elixir/](http://culttt.com/2016/08/24/understanding-genserver-elixir/)
* [https://medium.com/blackode/when-and-where-to-use-cast-cal-info-messages-in-elixir-erlang-genserver-9baf937b6494](https://medium.com/blackode/when-and-where-to-use-cast-cal-info-messages-in-elixir-erlang-genserver-9baf937b6494)