Elixir:如果服务器重启,如何持久保存OTP队列?

时间:2017-04-20 06:13:34

标签: elixir phoenix-framework otp

我正在使用OTP来管理事件队列:

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

我的问题是,如果服务器重新启动,我的队列会发生什么?重启后我需要它才能坚持下去。据我所知,它存储在内存中,因此如果服务器重新启动就会被擦除。

2 个答案:

答案 0 :(得分:4)

我创建了一个单独的代理来跟踪GenServer中的状态。代理非常简单,具有更新状态的API,并根据请求获取它。

我在GenServer中创建了reply(state, result)noreply(state)个函数,并在handle_callhandle_casthandle_info函数的末尾调用它们。

replyno_reply函数将state放入代理中,然后返回{:no_reply, state}{:reply, result, state}元组。我还在终止时更新代理。

当服务器重新启动时,我会检查它是否重启,如果是,请从genservers init回调中的代理中提取状态。我只是检查代理商。如果它没有数据,我知道是原始启动。

这里的想法是Agent是一个非常简单的值存储。它非常简单,不太可能失败。

但是你应该小心这种方法。重启策略背后的想法是GenServer以其初始状态重新启动。如果GenServer由于状态问题而重新启动,则可能会进入连续重启状态。

答案 1 :(得分:1)

如果服务器重启,如果服务器是指整个机器而不仅仅是genserver,那么它是正确的。我建议将队列存储在持久存储中,如数据库或redis。