Elixir GenServer Callbacks
GenServer callbacks are functions that run when a message reaches a server process. Each callback handles one kind of message and returns what the server answers and what it keeps.
init sets the first value
The init callback runs once at start. Here it stores the name it is given.
defmodule Greeter do
use GenServer
def init(name), do: {:ok, name}
def handle_call(:hello, _from, name), do: {:reply, "Hello, " <> name, name}
end
{:ok, server} = GenServer.start_link(Greeter, "Ana")
IO.puts(GenServer.call(server, :hello))
GenServer.stop(server)handle_cast handles a message without a reply
A cast sends a message and moves on at once. The next call reads the stored note.
defmodule Notebook do
use GenServer
def init(text), do: {:ok, text}
def handle_cast({:note, text}, _state), do: {:noreply, text}
def handle_call(:read, _from, state), do: {:reply, state, state}
end
{:ok, server} = GenServer.start_link(Notebook, "")
GenServer.cast(server, {:note, "Buy milk"})
IO.puts(GenServer.call(server, :read))
GenServer.stop(server)handle_info handles a plain sent message
A message sent straight to the server lands in handle_info. The call after it reads the new count.
defmodule Ticker do
use GenServer
def init(_arg), do: {:ok, 0}
def handle_info(:tick, count), do: {:noreply, count + 1}
def handle_call(:get, _from, count), do: {:reply, count, count}
end
{:ok, server} = GenServer.start_link(Ticker, [])
send(server, :tick)
IO.inspect(GenServer.call(server, :get))
GenServer.stop(server)Example
defmodule Bell do
use GenServer
def init(_arg), do: {:ok, 0}
def handle_call(:count, _from, count), do: {:reply, count, count}
def handle_cast(:ring, count), do: {:noreply, count + 1}
def handle_info(:reset, _count), do: {:noreply, 0}
end
{:ok, server} = GenServer.start_link(Bell, [])
GenServer.cast(server, :ring)
GenServer.cast(server, :ring)
IO.inspect(GenServer.call(server, :count))
send(server, :reset)
IO.inspect(GenServer.call(server, :count))
GenServer.stop(server)Key points
- GenServer: a server process built from callback functions.
- init: the callback that runs once when the server starts and sets its first value.
- handle_call: the callback that answers a caller that waits for a reply.
- handle_cast: the callback that handles a message sent without waiting for a reply.
- handle_info: the callback that handles any other message sent straight to the server.
- start_link: the function that starts a server and links it to the caller.
In this example, Bell starts at 0 through init. Two ring casts raise the count to 2, and a call reads 2. A reset message then reaches handle_info and drops the count to 0, and a second call reads 0. The server is stopped at the end.
Note
a server started without a name is reached through the value start_link returns.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
Which callback answers a caller that waits for a reply?