Start an Agent with the module name instead of anonymous function

The Elixir documentation for start_link(module, fun, args, options \\ []) doesn’t have any example on how to use it:

@spec start_link(module(), atom(), [any()], GenServer.options()) :: on_start()

Starts an agent linked to the current process.

Same as start_link/2 but a module, function, and arguments are expected instead of an 
anonymous function; fun in module will be called with the given arguments args to initialize the state.

My current code to initialize the Agent with a module name:

defmodule UdpServer.ServersAgent do
  use Agent
  alias UdpServer.ServersAgent

  defstruct [
    servers: %{},
    tracked_packets: %{},
  ]

  def start_link(args) do
    IO.inspect(args, label: "SERVERS ARGS")
    # Agent.start_link(fn -> %ServersAgent{} end, name: __MODULE__)
    Agent.start_link(__MODULE__, :initial_state, args)
  end

  # Function isn't called as the docs seems to say.
  def initial_state(args) do
    IO.puts("initial_state/1")
    %ServersAgent{}
  end

  # Function its called but the Agent isn't started 
  def initial_state() do
    IO.puts("initial_state/0")
    #  %ServersAgent{}
    fn -> %ServersAgent{} end
  end

  ### omitted some code ... ###
end

What am I missing or doing wrong?

args is a list of parameters not a value to pass. So you want to wrap args in a list to call the arity-1 function. This mimics how mfa data is passed to apply/3 and many other similar functions.
Agent.start_link(__MODULE__, :initial_state, [args])

1 Like

That indeed makes the initial_state/1 to be called, but the Agent still fails to start and I don’t get an error, unless I try to use it:

def state() do
    Agent.get(__MODULE__, fn state -> state end)
end

It seems that starting the Agent with Agent.start_link(__MODULE__, :initial_state, [args]) may not register the Agent with the module name :thinking:

iex(1)> UdpServer.ServersAgent.state
** (exit) exited in: GenServer.call(UdpServer.ServersAgent, {:get, #Function<10.7153398/1 in UdpServer.ServersAgent.state/0>}, 5000)
    ** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
    (elixir 1.14.2) lib/gen_server.ex:1027: GenServer.call/3
    iex:1: (file)

Need to pass it through the options:

Agent.start_link(__MODULE__, :initial_state, [args], name: __MODULE__)