我有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
答案 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
的开头获取此值。