Elixir: restart GenServer with specific action
Let's say I have an instance GenServer
:
defmodule MyModule do
use GenServer
def init(_) do
{:ok, %{}}
end
#...
end
I want MyModule to be monitored, but when it crashes, do something before it reloads with pre-crashing state:
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
But I'm not sure how to implement this.
source to share
I remember it was described in a book by Dave Thomas. The idea is to have another process that retains the replica of the state. This process has one job: tracking changes in state. This should prevent it from crashing (if the original process notifies the watcher of a state change, that means it doesn't crash when the changes are applied).
Then, when the original process crashes and restarts, it can simply retrieve the previous state from the backup process (it needs to get the PID of that process from the supervisor).
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
source to share