在Elixir中创建多进程缓存

时间:2016-08-15 15:55:55

标签: erlang elixir

我正在阅读7 concurrency models in 7 weeks并且作者要求实施

  

缓存,根据多个actor分配缓存条目   到哈希函数。创建一个启动多个缓存的管理程序   actor将传入的消息路由到适当的缓存工作者。   如果其中一个缓存工作者,该主管应该采取什么行动   失败?

defmodule CacheSupervisor do
  def start(number_of_caches) do
    spawn(__MODULE__, :init, [number_of_caches])
  end

  def init(number_of_caches) do
    Process.flag(:trap_exit, true)

    pids = Enum.into(Enum.map(0..number_of_caches-1, fn(id) ->
                                         {id, Cache.start}
                                     end), %{})

    loop(pids, number_of_caches)
  end

  def loop(pids, number_of_caches) do
    receive do
        {:put, url, page} -> send(compute_cache_pid(pids, url, number_of_caches), {:put, url, page})
                            loop(pids, number_of_caches)
        {:get, sender, ref, url} -> send(compute_cache_pid(pids, url, number_of_caches), {:get, sender, ref, url})
                                    loop(pids, number_of_caches)
        {:EXIT, pid, reason} -> IO.puts("Cache #{pid} failed with reason #{inspect reason} - restarting it")
                                loop(repair(pids, pid), number_of_caches)
    end
  end

  def restart(pids, pid) do
    #not clear how to repair, since we don't know the index of the failed process
  end

  def compute_cache_pid(pids, url, number_of_caches) do
    pids[rem(:erlang.phash2(url), number_of_caches)]
  end
end

当进程失败时,主管只获取其pid。仅使用pid,我无法理解哪个存储桶需要新进程。我可能会创建第二张地图pid -> bucket_index,但它看起来很难看。

当我生成进程时,我可以以某种方式附加其他属性吗?进程退出时可以读取这些属性吗?

解决问题的最佳方式是什么(没有OTP)?

这种实施也使主管也变得聪明"。据我所知,主管应该很简单,只关心重启失败的流程。

我不确定如何将重启和路由逻辑分成两个独立的进程:当主管重启某个进程时,路由器应该知道它并拥有最新的pids

0 个答案:

没有答案