由于名称不正确,调用 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
]
尽管名称必须是 MyLib.Cache
- 带点,但为什么当我指定名称时它可以工作:MyLibCache
(没有点)?
我希望能够在 GenServer 中使用 name: __MODULE__
。但是有了它,它将无法在 application.ex
中启动它,因为它找不到具有这样名称的模块。如何解决?
更新:
运行时出错,仅尝试访问调用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 registration 的 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
]
尽管名称必须是
MyLib.Cache
- 带点,但为什么当我指定名称时它可以工作:MyLibCache
(没有点)?我希望能够在 GenServer 中使用
name: __MODULE__
。但是有了它,它将无法在application.ex
中启动它,因为它找不到具有这样名称的模块。如何解决?
更新:
运行时出错,仅尝试访问调用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 registration 的 name
参数了解详情。