自己紹介

:ets.give_away/3

ETSテーブルとは

解決策

  • もう一個のManagerプロセスを作る

              http://steve.vinoski.net/blog/2011/03/23/dont-lose-your-ets-tables/

:ets.give_awayでオーナーを変える

SupervisorがServerとManagerを起動

      def start(_type, _args) do
        ...
        children = [
        worker(EtsGive.Server, []),
        worker(EtsGive.Manager, [])
        ]
      ...
      Supervisor.start_link(children, opts)
      

Managerの中にtrap_exitをtrueに設定

      def init(:ok) do
        # Serverが死んでもManagerを死なないようにするため
        Process.flag(:trap_exit, true)
        gift()
        {:ok, %State{}}
      end
      

Managerが後継者を自分だとして設定

      :ets.setopts(table_id, {:heir, self(), data})
      :ets.give_away(table_id, server, data)
      

gift()関数 link -> setopts -> give_away

      def handle_cast({:gift, data}, state) do
        server = Process.whereis(EtsGive.Server)
        Process.link(server) <----

        table_id = :ets.new(@name, [:private])
        :ets.insert(table_id, data)

        :ets.setopts(table_id, {:heir, self(), data}) <----
        :ets.give_away(table_id, server, data)  <----

        {:noreply, struct(state, table_id: table_id)}
      end
      

Serverが死ぬと, ETS-TRANSFERメッセージくる

      def handle_info({:'ETS-TRANSFER', table_id, from, data}, state) do
        server = wait_for_server()

        Process.link(server)
        :ets.give_away(table_id, server, data)

        {:noreply, struct(state, table_id: table_id)}
      end
      

参照リンク

/