Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Agent

notebooks/agent.livemd

Agent

description

Agent module

  • manage state in a process
  • wraps the GenServer behaviour

simple stack with Agent

  • house all Agent calls
  • abstract away how it works under the hood
  • start the Agent as a named process so we can reference the process by name
defmodule MyStack do
  use Agent

  def start_link(initial_state \\ []) do
    # synchronously start the Agent process
    Agent.start_link(
      fn -> initial_state end,
      name: __MODULE__
    )
  end

  def stop do
    # synchronously stop the Agent process
    Agent.stop(__MODULE__)
  end

  def push(element) do
    Agent.update(
      __MODULE__,
      fn state -> [element | state] end
    )
  end

  def pop do
    # get and update the agent state in one operation
    Agent.get_and_update(
      __MODULE__,
      fn
        [] ->
          {_result, _new_state} = {{:error, "empty stack"}, []}

        [head | rest] ->
          {_result, _new_state} = {head, rest}
      end
    )
  end

  def inspect do
    Agent.get(
      __MODULE__,
      fn state -> state end
    )
  end
end
MyStack.start_link([])

MyStack.inspect()
for value <- 1..10 do
  MyStack.push(value)
end

MyStack.inspect()
MyStack.pop()
MyStack.stop()
# `use Agent` generates `child_spec/1`
MyStack.child_spec([])

Process introspection

description

  • extract the state of processes
  • see the memory usage of individual processes
  • etc

tools and techniques

MyStack.start_link([])
pid = Process.whereis(MyStack)

Process.info(pid)
:sys.get_state(MyStack)
:sys.replace_state(MyStack, fn state -> [123 | state] end)
:sys.get_status(MyStack)
# List all the PIDs currently executing on the current BEAM instance
Process.list()
# find the process with the largest total heap size
# (how much memory the process is using)
Process.list()
|> Enum.max_by(fn pid -> Process.info(pid, :total_heap_size) end)
|> Process.info()
# find the process with the highest reduction count
Process.list()
|> Enum.max_by(fn pid -> Process.info(pid, :reductions) end)
|> Process.info()