Elixir Agent - A simple way to sharing data between processes without implement process or GenServer
Mạnh Vũ
Posted on July 4, 2024
Intro
For newbies, it's hard for fully understanding Elixir process (also GenServer
). For easy to work with process, Elixir provides Agent
module to support sharing data (state) between two or more processes.
Explain
In Elixir, every single line of code is run in a process and because Elixir is functional programming then we don't have global variable (of course, we have a big benefit for this that is much more less side effect - From avoided using global variable).
To share data between functions we use process dictionary or pass variable as param.
But for between different processes we need more effort to share data (if not used Ets table & :persistent_term
- a limited way). We need add code to send & receive a message, also we need to handle state to store global variable (can use process dictionary).
For much more convenient to sharing data between process we can use Agent
for holding global data (state) to share between processes or simple between functions in different point of times in a process.
Implement a Agent
We can implement a module using Agent
or directly (less convenient).
defmodule AutoId do
use Agent
def start_link(initial_id) do
Agent.start_link(fn -> initial_id end, name: __MODULE__)
end
def last_id do
Agent.get(__MODULE__, & &1)
end
def set_id(new_id) do
Agent.update(__MODULE__, fn _old -> id end)
end
def new_id do
Agent.get_and_update(__MODULE__, fn id -> {id, id + 1} end)
end
end
In this example, we make a module to sharing a way to get unique id for all processes in system by call AudoId.new_id()
.
We can add to a application supervisor or manual start by call AutoId.start_link(0)
before using (remember Agent process will crash if our process is crashed).
To add to a application supervisor (or our supervisor) we add code like:
children = [
{AutoId, 0}
]
Supervisor.start_link(children, strategy: :one_for_one)
For starting manual AutoId
process just add code like:
AutoId.start_link(1_000)
And in somewhere in source code we can use by call AutoId
functions like:
my_id = AutoId.new_id()
#...
# reset id
AutoId.set_id(1_000_000)
other_id = AutoId.new_id()
Agent
is simple enough for using and we don't need implement GenServer
or write new process for sharing data.
Agent
is process then it can be hangover or overload, for in case we need get/set data (state) in limited time we can use timeout
param (default is 5_000 ms).
Agent
also provides config for child_spec
for supervisor like GenServer
& support distributed, hot code swapping for more use cases.
Posted on July 4, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.