我正在尝试将Agent用作商店。但是,我遇到的问题是我存储数据的密钥不存在。
这是我的频道:
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. says they matched_client_email key does not exist in Agent.
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
我被建议为此创建一个主管,但我不确定如何。我知道我必须在lib / my_app.exs中添加一些注释掉的行,但我找不到。我也不是100%肯定这会解决我的问题。
def start(_type, _args) do
import Supervisor.Spec
# Define workers and child supervisors to be supervised
children = [
# Start the Ecto repository
supervisor(VideoChat.Repo, []),
# Start the endpoint when the application starts
supervisor(VideoChat.Endpoint, []),
# Start your own worker by calling: VideoChat.Worker.start_link(arg1, arg2, arg3)
# worker(VideoChat.Worker, [arg1, arg2, arg3]),
]
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: VideoChat.Supervisor]
Supervisor.start_link(children, opts)
end
答案 0 :(得分:3)
取消注释
# worker(VideoChat.Worker, [])
在那里传递适当的模块而不是VideoChat.Worker
。参数将传递给相应的VideoChat.Worker.start_link
函数。崩溃后,将重新启动此特定Agent
。以下是一个人为的例子:
<强> LIB / my_app.ex 强>
children = [
# Start the Ecto repository
supervisor(VideoChat.Repo, []),
# Start the endpoint when the application starts
supervisor(VideoChat.Endpoint, []),
# start our own agent
worker(VideoChat.Store, [])
]
<强> LIB / video_chat / store.ex 强>
defmodule VideoChat.Store do
@moduledoc "The store, based on `Agent`."
def start_link do
Agent.start_link(fn -> %{} end, name: __MODULE__)
end
@doc "Gets a value"
@spec get(String.t) :: Map.t
def get(key) do
Agent.get(__MODULE__, &Map.get(&1, key))
end
@doc "Puts a value"
@spec put(String.t, {String.t, any}) :: Map.t
def put(key, {inner_key, inner_value}) do
# more sophisticated implementation,
# possibly based on `Agent.get_and_update/3`
end
end
答案 1 :(得分:0)
请考虑this example。它监督GenServer,但Agent 是 GenServer,因此它与代码非常相似。
首先,您应该创建自己的模块进行监督 - 它将使用内部代理(就像在doc中的示例,但GenServer被包装)。
然后你可以创建自己的Supervisor模块,并在init
函数中将孩子声明为工人,例如。
children = [ worker(MyAgent, [[]])] # [] as an initial state
您还可以init
使用supervise
来选择策略如何运作,当其中一名员工崩溃时。
要监督流程,您必须先启动主管,并且应该启动所有具有初始状态的子工作者。