由于名称不正确,调用 GenServer 失败

Calling a GenServer fails due to an incorrect name

我在库中有这个 GenServer:

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
  # [.........]

而这个应用程序:

    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
        ]

更新:

运行时出错,尝试访问调用Cache的页面时,即启动时不出错:

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

也就是说,这将不会出错:

GenServer.start_link(__MODULE__, %{}, name: MyLibCache)
# or 
# GenServer.start_link(__MODULE__, %{}, name: MyLib.Cache) # with dot

这个 - 上面显示的错误:

GenServer.start_link(__MODULE__, %{}, name: __MODULE__)

Supervisor.Spec 自 Elixir 1.5 以来已被弃用。您不需要使用它。这是一个工作示例:

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

然后在 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?

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 registrationname 参数了解详情。