Agent
Simple wrapper of genserver for state
creates child_spec/1 function that start agent directly under a supervisor.
single threaded state management, updates require new object(ETS much more scalable, but agent good for smaller use cases)
genserver with specific functions for get, update, cast that operate on state and combining server and client code into one function
defmodule Counter do
use Agent
def start_link(initial_value) do
Agent.start_link(fn -> initial_value end, name: __MODULE__)
end
def value do
#gets agent state, applies ft, then returns
Agent.get(__MODULE__, & &1)
end
def increment do
#applies ft to the state and updates it
Agent.update(__MODULE__, &(&1 + 1))
end
end
Usage
Counter.start_link(0) #=> {:ok, #PID<0.123.0>}
Counter.value() #=> 0
Counter.increment() #=> :ok
Counter.increment() #=> :ok
Counter.value() #=> 2
Considerations
Atomic updates because server fns run one by one
Should therefore put long running processes in client(not inside agent ft calls), because it will block the agent from recieving other calls from other processes
Raw
Keep a process running that loops infinitely maintaining state and sending/recieving messages
defmodule KV do
def start_link do
Task.start_link(fn -> loop(%{}) end)
end
#defp makes it private
defp loop(map) do
receive do
{:get, key, caller} ->
send caller, Map.get(map, key)
loop(map)
{:put, key, value} ->
loop(Map.put(map, key, value))
end
end
end
Can then register a pid giving it a name avaliable to all
Process.register(pid, :kv)
send :kv, {:get, :hello, self()}
Last updated