53 lines
1.0 KiB
Elixir
53 lines
1.0 KiB
Elixir
defmodule Counter.Worker do
|
|
use GenServer
|
|
|
|
@registry Counter.Registry
|
|
@table Counter.Table
|
|
|
|
### Client API ###
|
|
def start_link(name) do
|
|
GenServer.start_link(__MODULE__, name, name: via(name))
|
|
end
|
|
|
|
def value(name) do
|
|
GenServer.call(via(name), :value)
|
|
end
|
|
|
|
def inc(name, amt \\ 1) do
|
|
GenServer.cast(via(name), {:inc, amt})
|
|
end
|
|
|
|
# wrap the name in a triple to use the Registry to get the
|
|
# process ID by name
|
|
defp via(name) do
|
|
{:via, Registry, {@registry, {__MODULE__, name}}}
|
|
end
|
|
|
|
### Server Impl ###
|
|
@impl true
|
|
def init(arg) do
|
|
name = {__MODULE__, arg}
|
|
value = case :ets.lookup(@table, name) do
|
|
[] -> 0
|
|
[{_, v}] -> v
|
|
end
|
|
{:ok, {name, value}}
|
|
end
|
|
|
|
@impl true
|
|
def handle_call(:value, _from, {_, value} = state) do
|
|
{:reply, value, state}
|
|
end
|
|
|
|
@impl true
|
|
def handle_cast({:inc, amt}, {name, value}) do
|
|
{:noreply, {name, value + amt}}
|
|
end
|
|
|
|
# save state to term table when process terminates
|
|
@impl true
|
|
def terminate(_, state) do
|
|
:ets.insert(@table, state)
|
|
end
|
|
end
|