使用Genserver订阅Phoenix PubSub的正确方法
Correct way of subscribing to Phoenix PubSub with Genserver
我一直在尝试实例化一个将在 Phoenix 框架中订阅 PubSub 的 genserver 进程,这些是我的文件和错误:
config.ex:
config :excalibur, Excalibur.Endpoint,
pubsub: [
adapter: Phoenix.PubSub.PG2,
name: Excalibur.PubSub
]
使用 genserver 的模块:
defmodule RulesEngine.Router do
import RulesEngine.Evaluator
use GenServer
alias Excalibur.PubSub
def start_link(_) do
GenServer.start_link(__MODULE__, name: __MODULE__)
end
def init(_) do
{:ok, {Phoenix.PubSub.subscribe(PubSub, :evaluator)}}
IO.puts("subscribed")
end
# Callbacks
def handle_info(%{}) do
IO.puts("received")
end
def handle_call({:get, key}, _from, state) do
{:reply, Map.fetch!(state, key), state}
end
end
当我执行 iex -S mix 时,会发生此错误:
** (Mix) Could not start application excalibur: Excalibur.Application.start(:normal, []) returned an error: shutdown: failed to start child: RulesEngine.Router
** (EXIT) an exception was raised:
** (FunctionClauseError) no function clause matching in Phoenix.PubSub.subscribe/2
(phoenix_pubsub 1.1.2) lib/phoenix/pubsub.ex:151: Phoenix.PubSub.subscribe(Excalibur.PubSub, :evaluator)
(excalibur 0.1.0) lib/rules_engine/router.ex:11: RulesEngine.Router.init/1
(stdlib 3.12.1) gen_server.erl:374: :gen_server.init_it/2
(stdlib 3.12.1) gen_server.erl:342: :gen_server.init_it/6
(stdlib 3.12.1) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
那么启动将订阅 PubSub 主题的 Genserver 的正确方法是什么?
根据文档,Phoenix.PubSub.subscribe/3
具有以下规范:
@spec subscribe(t(), topic(), keyword()) :: :ok | {:error, term()}
其中 @type topic :: binary()
。也就是说,您的 init/1
应该看起来像
def init(_) do
{:ok, {Phoenix.PubSub.subscribe(PubSub, "evaluator")}}
|> IO.inspect(label: "subscribed")
end
请注意,我还将 IO.puts/1
更改为 IO.inspect/2
以保留返回值。
我一直在尝试实例化一个将在 Phoenix 框架中订阅 PubSub 的 genserver 进程,这些是我的文件和错误:
config.ex:
config :excalibur, Excalibur.Endpoint,
pubsub: [
adapter: Phoenix.PubSub.PG2,
name: Excalibur.PubSub
]
使用 genserver 的模块:
defmodule RulesEngine.Router do
import RulesEngine.Evaluator
use GenServer
alias Excalibur.PubSub
def start_link(_) do
GenServer.start_link(__MODULE__, name: __MODULE__)
end
def init(_) do
{:ok, {Phoenix.PubSub.subscribe(PubSub, :evaluator)}}
IO.puts("subscribed")
end
# Callbacks
def handle_info(%{}) do
IO.puts("received")
end
def handle_call({:get, key}, _from, state) do
{:reply, Map.fetch!(state, key), state}
end
end
当我执行 iex -S mix 时,会发生此错误:
** (Mix) Could not start application excalibur: Excalibur.Application.start(:normal, []) returned an error: shutdown: failed to start child: RulesEngine.Router
** (EXIT) an exception was raised:
** (FunctionClauseError) no function clause matching in Phoenix.PubSub.subscribe/2
(phoenix_pubsub 1.1.2) lib/phoenix/pubsub.ex:151: Phoenix.PubSub.subscribe(Excalibur.PubSub, :evaluator)
(excalibur 0.1.0) lib/rules_engine/router.ex:11: RulesEngine.Router.init/1
(stdlib 3.12.1) gen_server.erl:374: :gen_server.init_it/2
(stdlib 3.12.1) gen_server.erl:342: :gen_server.init_it/6
(stdlib 3.12.1) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
那么启动将订阅 PubSub 主题的 Genserver 的正确方法是什么?
根据文档,Phoenix.PubSub.subscribe/3
具有以下规范:
@spec subscribe(t(), topic(), keyword()) :: :ok | {:error, term()}
其中 @type topic :: binary()
。也就是说,您的 init/1
应该看起来像
def init(_) do
{:ok, {Phoenix.PubSub.subscribe(PubSub, "evaluator")}}
|> IO.inspect(label: "subscribed")
end
请注意,我还将 IO.puts/1
更改为 IO.inspect/2
以保留返回值。