当工人重新开始时,主管仍处于状态

时间:2017-08-17 02:04:55

标签: elixir

我有AgentTest作为保持状态的工作人员,Supv作为监视器的主管AgentTest

 defmodule AgentTest do
  use Agent

  def start_link(state) do
    Agent.start_link(fn -> state end, name: :test) 
  end

  def incr do
    Agent.get_and_update(:test, fn state -> {state, state + 1} end) 
  end

  def crash do
    Agent.stop(:test, :crash) 
  end

  def get do
    Agent.get(:test, fn state -> state end) 
  end
end

defmodule Supv do
  use Supervisor

  def start_link do
    Supervisor.start_link(Supv, []) 
  end

  def init(_arg) do
    Supervisor.init([
      {AgentTest, 1} 
    ], strategy: :one_for_one) 
  end
end

我试过iex,重启时状态不会停留:

iex(2)> Supv.start_link
{:ok, #PID<0.99.0>}
iex(3)> AgentTest.incr
1
iex(4)> AgentTest.incr
2
iex(5)> AgentTest.get
3
iex(6)> AgentTest.get
3
iex(7)> AgentTest.crash
:ok
iex(8)>
10:03:26.560 [error] GenServer :test terminating
** (stop) :crash
Last message: []
State: 3

nil
iex(9)> AgentTest.get
1

如何在AgentTest重新启动时保持Supv状态?

我正在使用Elixir 1.5

2 个答案:

答案 0 :(得分:0)

为了保留状态,您可以运行一个单独的进程,该进程将存储一个存储值。

defmodule Supv do
  use Supervisor

  def start_link do
    children = [
      worker(Stash, [1]),
      worker(AgentTest, [])
    ]

    Supervisor.start_link(Supv, children)
  end

  def init(children) do
    supervise children, strategy: :one_for_one
  end
end

当主AgentTest进程终止时,它会将其当前值放入存储中。当重新启动进程时,它会从存储中获取值:

defmodule AgentTest do
  use Agent

  def start_link do
    Agent.start_link(fn -> Stash.get() end, name: :test)
  end

  def incr do
    Agent.get_and_update(:test, fn state -> {state, state + 1} end)
  end

  def crash do
    Stash.update(get())

    Agent.stop(:test, :crash)
  end

  def get do
    Agent.get(:test, fn state -> state end)
  end
end

存储过程可以很简单Agent

defmodule Stash do
  use Agent

  def start_link(initial_number) do
    Agent.start_link(fn -> initial_number end, name: :stash)
  end

  def get do
    Agent.get(:stash, fn state -> state end)
  end

  def update(number) do
    Agent.update(:stash, fn _ -> number end)
  end
end

为了简化示例,我将流程命名为:stash),但其pid当然可以作为参数传递给AgentTest

答案 1 :(得分:0)

您始终可以使用:ets。对于每次更新,您也可以将此信息存储在ets中,并在start_link的开头获取此值。