Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elixir: How to persist OTP queue if server restarts?

I am using OTP for managing a queue of events:

defmodule ParrotApi.MatchingSupervisor do
  use Supervisor

  ## Callbacks

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

  def init(_) do
    children = [
      worker(ParrotApi.MatchingServer, []), # TODO: State is gone if this crashes

      # Supervise connections
      supervisor(Registry, [:unique, :connection_registry]),
      supervisor(ParrotApi.ConnectionSupervisor, []),
    ]

    supervise(children, strategy: :one_for_one)
  end
end

My question is, if the server restarts, what happens to my queue? I need it to persist after restarting. To my knowledge it is stored in memory so it is wiped if the server restarts.

like image 858
bigpotato Avatar asked Mar 09 '23 07:03

bigpotato


1 Answers

I create a separate Agent to track the state in the GenServer. The Agent is very simple, with an API to update the state, and fetch it upon request.

I create reply(state, result) and noreply(state) functions in the GenServer and call them at the end of the handle_call, handle_cast, and handle_info functions.

The reply and no_reply functions put the state in the Agent and then return the {:no_reply, state} and {:reply, result, state} tuples. I also update the agent on terminate.

When the server restarts, I check to see if its a restart and if so, pull the state from the agent in the genservers init callback. I just check the agent. If it does not have data, I know is a the original startup.

The idea here is that the Agent is a very simple value store. Its very simple and unlikely to fail.

You should be careful with this approach though. The idea behind the restart strategy is that the GenServer is restarted with its initial state. If your GenServer restarted because of an issue with its state, it may get into a continuous restart state.

like image 78
Steve Pallen Avatar answered Mar 11 '23 21:03

Steve Pallen