Show Notes

There are three main deployment targets for an Elixir app:

  1. PAAS (Heroku)
  2. Embedded Device (Nerves project)
  3. Self-managed Hardware (ExRM)

This episode focuses on the last: how to deploy to self-managed hardware using ExRM. The ExRM docs contain the latest instructions on how to use it.

GenServer Upgrading

During a hot code upgrade, most modules can be upgraded by just “swapping” their code in memory out for a new version. However, GenServer processes are a bit different.

If you simply replaced a GenServer callback module without doing anything else, the process could crash. This would happen if the new version of the module expected the process state to be formatted differently than the old module did. The state persists during the hot code upgrade, so if you change its format, you must provide some migration instructions on how to upgrade the state to be compatible with the new version.

For this reason, it can be a good idea to tag your GenServer modules with a @vsn attribute, even before you ever do a hot code upgrade.

defmodule BankAccount do
  use GenServer
  
  @vsn "1.0.0"
end

This @vsn attribute helps the BEAM virtual machine perform state migrations, when you pair it with a code_change callback:

@vsn "2.0.0"

def code_change("1.0.0", balance, _extra) do
  new_state = %{debits: [], credits: [balance]}
  {:ok, new_state}
end

def code_change({:down, "2.0.0"}, state, _extra) do
  new_state = Enum.sum(state.credits) - Enum.sum(state.debits)
  {:ok, new_state}
end

This code takes the “1.0.0” state, which is just a number, and transforms it into a map of debits and credits. It also provides a downgrade definition. After the hot code upgrade is complete, you can remove these callbacks.

Exercises

  1. Read the ExRM docs.
  2. Deploy an Elixir app using ExRM.

Resources

Comments