凤凰城:如何监督代理商?

时间:2017-03-02 00:24:38

标签: elixir phoenix-framework

我正在尝试将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

2 个答案:

答案 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

Agent.get_and_update/3

答案 1 :(得分:0)

请考虑this example。它监督GenServer,但Agent GenServer,因此它与代码非常相似。

首先,您应该创建自己的模块进行监督 - 它将使用内部代理(就像在doc中的示例,但GenServer被包装)。

然后你可以创建自己的Supervisor模块,并在init函数中将孩子声明为工人,例如。

children = [ worker(MyAgent, [[]])] # [] as an initial state

您还可以init使用supervise来选择策略如何运作,当其中一名员工崩溃时。

要监督流程,您必须先启动主管,并且应该启动所有具有初始状态的子工作者。