I have this GenServer in a library:
defmodule MyLib.Cache do
use GenServer
def start_link([]) do
IO.puts("****cache genserver, name: #{__MODULE__}")
# GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
GenServer.start_link(__MODULE__, %{}, name: MyLibCache) # no dot
end
# [.........]
And this application:
defmodule MyApp.Application do
use Application
def start(_type, _args) do
import Supervisor.Spec
children = [
{Phoenix.PubSub, [name: MyApp.PubSub, adapter: Phoenix.PubSub.PG2]},
{MyLib.Repo, []},
{MyAppWeb.Endpoint, []},
{MyLib.Cache, []} # notice the dot
]
Why is it working work when I specify name: MyLibCache
(without a dot) although the name must be MyLib.Cache
- with a dot?
I want to be able to use name: __MODULE__
in the GenServer. But with it, it'll fail to start it in application.ex
because it won't find the module with such a name. How to fix it?
update:
error at runtime, only when I try to access a page where Cache is called, that is, not at startup:
exited in: GenServer.call(MyLibCache, {:get, "Elixir.MyLib.Dal.User.2"}, 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
namely, this will work with no error:
GenServer.start_link(__MODULE__, %{}, name: MyLibCache)
# or
# GenServer.start_link(__MODULE__, %{}, name: MyLib.Cache) # with dot
this - with the error shown above:
GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
Supervisor.Spec
has been deprecated since Elixir 1.5. You do not need to use it. Here a working example:
defmodule MyLib.Cache do
use GenServer
def init(state), do: {:ok, state}
def start_link(state) do
GenServer.start_link(__MODULE__, state, name: __MODULE__)
end
end
Then in application.ex
:
def start(_type, _args) do
children = [
MyLib.Cache
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
Why is it working work when I specify name: MyLibCache (without a dot) although the name must be MyLib.Cache - with a dot?
The name
argument to GenServer.start_link/3
is the name of the server, not the module. They can be the same, but they don't have to be. The name you supply here is the name that needs to be supplied to Genserver.call/3
later. See Name registration for details.