Erlang Elixir:通过某些操作重新启动GenServer
假设我有Erlang Elixir:通过某些操作重新启动GenServer,erlang,elixir,otp,Erlang,Elixir,Otp,假设我有GenServer实例: defmodule MyModule do use GenServer def init(_) do {:ok, %{}} end #... end 我希望监视MyModule,但当它崩溃时,请在它重新启动之前使用崩溃前的状态执行以下操作: defmodule MyModule do use GenServer def init(_) do {:ok, %{}} end def init(:restart, pre
GenServer
实例:
defmodule MyModule do
use GenServer
def init(_) do
{:ok, %{}}
end
#...
end
我希望监视MyModule,但当它崩溃时,请在它重新启动之前使用崩溃前的状态执行以下操作:
defmodule MyModule do
use GenServer
def init(_) do
{:ok, %{}}
end
def init(:restart, previous_state) do
some_func(previous_state)
{:ok, previous_state}
end
#...
end
但我不知道如何实现这个我记得戴夫·托马斯的书中描述过这一点。其想法是使用另一个进程来保存状态的副本。此过程有一项任务:跟踪状态的更改。这应该可以防止它崩溃(如果原始进程将状态更改通知观察者,这意味着它在应用更改时没有崩溃) 然后,当原始进程崩溃并重新启动时,它可以从备份进程中获取以前的状态(它应该从管理器中获取该进程的PID)
您可以使用
terminate/2
回调并将状态存储在其他位置(代理、数据库、ETS)并将其加载到init/1
中,但我认为您无法使主管在重新启动时自动通过旧状态。您想对该状态做什么?除了日志记录之外,我无法想象一个用例,在这个用例中,同一个genserver会重用它的旧状态,而这恰恰导致了它的崩溃。如果您收到类似的消息,它不会立即再次崩溃吗?崩溃会向主管发送错误消息。你可能会抓住它,用它做点什么。否则,请使用Dogbert建议的方法将状态存储在某个位置,并使genserver在重新启动时从该位置加载。@Johannes我想说,在我的情况下,不是状态本身会导致崩溃,而是通过对此状态应用无效调用而引发的异常如果这些是有效的异常,为什么不从调用中的异常中恢复?
def start_link(backup_pid) do
GenServer.start_link(__MODULE__, backup_pid)
end
def init(backup_pid) do
state = Backup.get_state(backup_pid)
{:ok, state}
end
def terminate(_reason, state) do
Backup.save_state(state)
end