我有一个聊天应用程序,双方必须在进入聊天之前按“接受”。顺序如下:
Agent
将start_link
与派对合作
A的电子邮件地址为密钥Agent
将{B}的电子邮件地址作为密钥start_link
Agent
将存储Party
A's email -> Party B's email -> true
,否则会发送消息
乙方也接受了乙方。Agent
将存储Party A's email -> Party
B's email -> true
,否则会向甲方发送消息
也接受了。我现在遇到一个错误,它似乎不是
2017-03-01T14:02:40.434791+00:00 app[web.1]: 14:02:40.433 [error] GenServer #PID<0.1743.0> terminating
2017-03-01T14:02:40.434793+00:00 app[web.1]: ** (stop) exited in: GenServer.call(:"dhdjsjsjs@plabs.com", {:get, #Function<1.108716101/1 in VideoChat.CallChannel.handle_in/3>}, 5000)
2017-03-01T14:02:40.434794+00:00 app[web.1]: ** (EXIT) no process
2017-03-01T14:02:40.434795+00:00 app[web.1]: (elixir) lib/gen_server.ex:596: GenServer.call/3
2017-03-01T14:02:40.434795+00:00 app[web.1]: (video_chat) web/channels/call_channel.ex:152: VideoChat.CallChannel.handle_in/3
2017-03-01T14:02:40.434796+00:00 app[web.1]: (phoenix) lib/phoenix/channel/server.ex:226: anonymous fn/4 in Phoenix.Channel.Server.handle_info/2
2017-03-01T14:02:40.434797+00:00 app[web.1]: (stdlib) gen_server.erl:615: :gen_server.try_dispatch/4
2017-03-01T14:02:40.434798+00:00 app[web.1]: (stdlib) gen_server.erl:681: :gen_server.handle_msg/5
2017-03-01T14:02:40.434798+00:00 app[web.1]: (stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
这是我的频道:
def join("user_pool:" <> email, %{ "app" => app }, socket) do
Logger.info "PRODUCTION user_pool email: #{email}, app: #{app}"
socket = assign(socket, :email, email)
socket = assign(socket, :app, app)
Agent.start_link(fn -> %{} end, name: :"#{email}") # <---------------- should start link here
{:ok, socket}
end
def handle_in("approve_match", %{ "matched_client_email" => matched_client_email }, socket) do
Logger.info "approve_match"
current_user_email = socket.assigns[:email]
Agent.update :"#{current_user_email}", fn state ->
Map.put(state, matched_client_email, true)
end
match_accepted = Agent.get(:"#{matched_client_email}", &(Map.get(&1, current_user_email))) # <----------- breaks here. this is line 152
Logger.info "#{matched_client_email} has approved #{current_user_email}: #{match_accepted}"
case match_accepted do
true ->
VideoChat.Endpoint.broadcast(
"user_pool:#{matched_client_email}",
"match_accepted",
%{ matched_client_email: socket.assigns[:email] }
)
{:noreply, socket}
_ ->
Logger.info "2nd person has yet to approve"
{:noreply, socket}
end
end
当我在控制台中运行测试行时似乎没有中断:
iex(20)> Agent.start_link(fn -> %{} end, name: :"blah")
{:ok, #PID<0.365.0>}
iex(21)> Agent.get(:"blah", &(Map.get(&1, "sdfs")))
nil
我只是错误地使用Agent
吗?
答案 0 :(得分:1)
这是一条失败的行:
Agent.get(:"#{matched_client_email}" ...)
这是因为Agent
未必开始。您在测试中检查的内容是不同的,以复制您应该执行的行为:
iex(20)> Agent.start_link(fn -> %{} end, name: :"blah")
{:ok, #PID<0.365.0>}
iex(21)> Agent.get(:"foo", &(Map.get(&1, "sdfs"))) # NOTE :foo
可以明确检查目标Agent
是否已经开始,或try
/ catch
Agent.get
。
除此之外,你在没有受到监督的情况下产生代理人;当Agent
由于某种原因而失效时,可能会导致意外问题:它不会重新启动(保持关闭状态),您将会遇到上述行为。
我个人会选择一位受监督的Agent
,以email
作为关键持有一切。值可能会根据您的需要变得复杂,只需映射email
⇒%{}
。