I have this GenServer/client implementation for a naive cache using ETS:
defmodule Cache do
use GenServer
def start_link() do
GenServer.start_link(__MODULE__, [])
end
def fetch(key, def_value) do
case get(key) do
{:not_found} -> set(key, def_value)
{:found, result} -> result
end
end
defp get(key) do
case GenServer.call(__MODULE__, {:get, key}) do
[] -> {:not_found}
[{_, result}] -> {:found, result}
end
end
defp set(key, value) do
GenServer.call(__MODULE__, {:set, key, value})
end
# GenServer callbacks
def handle_call({:get, key}, _from, state) do
result = :ets.lookup(:my_table, key)
{:reply, result, state}
end
def handle_call({:set, key, value}, _from, state) do
true = :ets.insert(:my_table, {key, value})
{:reply, value, state}
end
def init(_args) do
:ets.new(:my_table, [:named_table, :set, :private])
{:ok, %{}}
end
end
I'm starting the server with:
$ iex -S mix
$ {:ok, pid} = Cache.start_link
{:ok, #PID<0.139.0>}
But when I call some function:
$ Cache.fetch(:key, "value")
I'm getting this error:
** (exit) exited in: GenServer.call(Cache, {:get, 1}, 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
Based on your GenServer.call
calls, I'm assuming you wanted to start a process registered with the same name as the module. In that case, you forgot to pass name: __MODULE__
to the GenServer.start_link
call in Cache.start_link
:
def start_link do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end