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.

+3


source to share


1 answer


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

      

+1


source







All Articles