Skip to content

Instantly share code, notes, and snippets.

@schmalz
Created September 22, 2017 15:20
Show Gist options
  • Save schmalz/deba894444a7260cbd366c78a8c9d5b2 to your computer and use it in GitHub Desktop.
Save schmalz/deba894444a7260cbd366c78a8c9d5b2 to your computer and use it in GitHub Desktop.
Designing for Scalability with Erlang/OTP - Ch 8 - Coffee Supervisor - Elixir
defmodule Sup do
def start(name, child_spec_list) do
Process.register(pid = spawn(__MODULE__, :init, [child_spec_list]), name)
{:ok, pid}
end
def stop(name), do: send(name, :stop)
def init(child_spec_list) do
Process.flag(:trap_exit, :true)
child_spec_list
|> start_children()
|> loop()
end
defp start_children(child_spec_list) do
for {m, f, a} <- child_spec_list, do: {elem(apply(m, f, a), 1), {m, f, a}}
end
defp loop(child_list) do
receive do
{:EXIT, pid, :normal} -> loop(List.keydelete(child_list, pid, 0))
{:EXIT, pid, _reason} -> loop(restart_child(pid, child_list))
:stop -> terminate(child_list)
end
end
defp restart_child(pid, child_list) do
{^pid, {m, f, a}} = List.keyfind(child_list, pid, 0)
{:ok, new_pid} = apply(m, f, a)
List.keyreplace(child_list, pid, 0, {new_pid, {m, f, a}})
end
defp terminate(child_list), do: Enum.each(child_list, fn({pid, _}) -> Process.exit(pid, :kill) end)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment