GenServer
Section
defmodule Bomb do
use GenServer
def start_link(opts) do
name = Keyword.get(opts, :name)
IO.inspect(opts, label: "GENSERVER #{name} WAS STARTED")
GenServer.start_link(__MODULE__, "init arg", name: __MODULE__)
end
def init(init_arg) do
IO.inspect(init_arg, label: "INIT FUNCTION WAS CALLED")
{:ok, []}
end
def handle_call(:detonate, _from, state) do
IO.inspect("detonate!")
{:reply, state, state}
end
def handle_info(:detonate, state) do
IO.inspect("detonating!")
{:noreply, state}
end
end
{:ok, pid} = Bomb.start_link([])
GenServer.call(pid, :detonate)
Process.send(Bomb, :detonate, [])
defmodule Counter do
use GenServer
def start_link(opts) do
IO.inspect(opts, label: "GENSERVER WAS STARTED")
GenServer.start_link(__MODULE__, opts)
end
@impl true
def init(init_arg) do
IO.inspect(init_arg, label: "INIT FUNCTION WAS CALLED")
{:ok, init_arg}
end
@impl true
def handle_info(:increment, state) do
next_state = state + 1
IO.inspect(state, label: "incrementing to #{next_state}")
{:noreply, next_state}
end
end
GenServer.start_link(Counter, 0)
{:ok, pid} = Counter.start_link(10)
Process.send(pid, :increment, [])
Traffic Light Server
defmodule TrafficLightClientAPI do
def start_link(_opts) do
GenServer.start_link(TrafficLightServerCallbacks, [])
end
def transition(pid) do
GenServer.call(pid, :switch)
end
end
defmodule TrafficLightServerCallbacks do
use GenServer
def init(_opts) do
{:ok, :green}
end
def handle_call(:switch, _from, state) do
next_light =
case state do
:green -> :yellow
:yellow -> :red
:red -> :green
end
{:reply, next_light, next_light}
end
end
Call vs Cast
Server Callback vs Client API
defmodule Counter do
use GenServer
# Server Callbacks
def init(_opts) do
IO.puts("Counter Initialized")
{:ok, 0}
end
# synchronous get_count
def handle_cast(:increment, state) do
GenServer.cast(self(), :log_count)
{:noreply, state + 1}
end
def handle_cast(:log_count, state) do
IO.inspect(state, label: "CURRENT COUNT")
{:noreply, state}
end
end
{:ok, pid} = GenServer.start_link(Counter, [])
GenServer.cast(pid, :increment)
:sys.get_state(pid)