我正在阅读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
。