diff --git a/lib/verk/manager_supervisor.ex b/lib/verk/manager_supervisor.ex new file mode 100644 index 0000000..9a34b26 --- /dev/null +++ b/lib/verk/manager_supervisor.ex @@ -0,0 +1,17 @@ +defmodule Verk.Manager.Supervisor do + @moduledoc false + use Supervisor + + @doc false + def start_link, do: Supervisor.start_link(__MODULE__, [], name: __MODULE__) + + @doc false + def init(_) do + queues = Confex.get_env(:verk, :queues, []) + children = for {queue, size} <- queues, do: Verk.Queue.Supervisor.child_spec(queue, size) + + children = [worker(Verk.Manager, [queues], id: Verk.Manager) | children] + + supervise(children, strategy: :rest_for_one) + end +end diff --git a/lib/verk/supervisor.ex b/lib/verk/supervisor.ex index 5ea20c1..cbaf5ae 100644 --- a/lib/verk/supervisor.ex +++ b/lib/verk/supervisor.ex @@ -9,47 +9,38 @@ defmodule Verk.Supervisor do """ use Supervisor - @doc false + @doc """ + It starts the main supervisor + """ def start_link do Supervisor.start_link(__MODULE__, [], name: __MODULE__) end @doc false def init(_) do - queues = Confex.get_env(:verk, :queues, []) - children = for {queue, size} <- queues, do: queue_child(queue, size) - redis_url = Confex.get_env(:verk, :redis_url) + redis = worker(Redix, [redis_url, [name: Verk.Redis]], id: Verk.Redis) + event_producer = worker(Verk.EventProducer, [], id: Verk.EventProducer) + queue_stats = worker(Verk.QueueStats, [], id: Verk.QueueStats) schedule_manager = worker(Verk.ScheduleManager, [], id: Verk.ScheduleManager) - event_producer = worker(Verk.EventProducer, []) - - queue_stats = worker(Verk.QueueStats, []) - redis = worker(Redix, [redis_url, [name: Verk.Redis]], id: Verk.Redis) + manager_sup = supervisor(Verk.Manager.Supervisor, [], id: Verk.Manager.Supervisor) - children = [redis, event_producer, queue_stats, schedule_manager] ++ children + children = [redis, event_producer, queue_stats, schedule_manager, manager_sup] supervise(children, strategy: :one_for_one) end @doc false def start_child(queue, size \\ 25) when is_atom(queue) and size > 0 do - Supervisor.start_child(__MODULE__, queue_child(queue, size)) + Supervisor.start_child(__MODULE__, Verk.Queue.Supervisor.child_spec(queue, size)) end @doc false def stop_child(queue) when is_atom(queue) do - name = supervisor_name(queue) + name = Verk.Queue.Supervisor.name(queue) case Supervisor.terminate_child(__MODULE__, name) do :ok -> Supervisor.delete_child(__MODULE__, name) error = {:error, :not_found} -> error end end - - defp queue_child(queue, size) when is_atom(queue) do - supervisor(Verk.Queue.Supervisor, [queue, size], id: supervisor_name(queue)) - end - - defp supervisor_name(queue) do - String.to_atom("#{queue}.supervisor") - end end diff --git a/test/manager_supervisor_test.exs b/test/manager_supervisor_test.exs new file mode 100644 index 0000000..bc52c7c --- /dev/null +++ b/test/manager_supervisor_test.exs @@ -0,0 +1,14 @@ +defmodule Verk.ManagerSupervisorTest do + use ExUnit.Case + import Verk.Manager.Supervisor + + describe "init/1" do + test "defines tree" do + {:ok, {_, children}} = init([]) + [manager, default] = children + + assert {Verk.Manager, _, _, _, :worker, [Verk.Manager]} = manager + assert {:"default.supervisor", _, _, _, :supervisor, [Verk.Queue.Supervisor]} = default + end + end +end diff --git a/test/supervisor_test.exs b/test/supervisor_test.exs index d7feca0..fa56147 100644 --- a/test/supervisor_test.exs +++ b/test/supervisor_test.exs @@ -1,16 +1,71 @@ defmodule Verk.SupervisorTest do use ExUnit.Case + import :meck + import Verk.Supervisor + + setup do + new Supervisor + on_exit fn -> unload() end + :ok + end describe "init/1" do test "defines tree" do - {:ok, {_, children}} = Verk.Supervisor.init([]) - [redix, producer, stats, schedule_manager, default] = children + {:ok, {_, children}} = init([]) + [redix, producer, stats, schedule_manager, manager_sup] = children assert {Verk.Redis, _, _, _, :worker, [Redix]} = redix assert {Verk.EventProducer, _, _, _, :worker, [Verk.EventProducer]} = producer assert {Verk.QueueStats, _, _, _, :worker, [Verk.QueueStats]} = stats assert {Verk.ScheduleManager, _, _, _, :worker, [Verk.ScheduleManager]} = schedule_manager - assert {:"default.supervisor", _, _, _, :supervisor, [Verk.Queue.Supervisor]} = default + assert {Verk.Manager.Supervisor, _, _, _, :supervisor, [Verk.Manager.Supervisor]} = manager_sup + end + end + + describe "start_child/2" do + test "add a new queue" do + queue = :test_queue + + child = { :"test_queue.supervisor", { Verk.Queue.Supervisor, :start_link, [:test_queue, 30] }, :permanent, :infinity, :supervisor, [ Verk.Queue.Supervisor ] } + expect(Supervisor, :start_child, [Verk.Supervisor, child], :ok) + + assert start_child(queue, 30) == :ok + + assert validate Supervisor end end + + describe "stop_child/1" do + test "a queue successfully" do + queue = :test_queue + + expect(Supervisor, :terminate_child, [Verk.Supervisor, :"test_queue.supervisor"], :ok) + expect(Supervisor, :delete_child, [Verk.Supervisor, :"test_queue.supervisor"], :ok) + + assert stop_child(queue) == :ok + + assert validate Supervisor + end + + test "a queue unsuccessfully terminating child" do + queue = :test_queue + + expect(Supervisor, :terminate_child, [Verk.Supervisor, :"test_queue.supervisor"], { :error, :not_found }) + + assert stop_child(queue) == { :error, :not_found } + + assert validate Supervisor + end + + test "a queue unsuccessfully deleting child" do + queue = :test_queue + + expect(Supervisor, :terminate_child, [Verk.Supervisor, :"test_queue.supervisor"], :ok) + expect(Supervisor, :delete_child, [Verk.Supervisor, :"test_queue.supervisor"], { :error, :not_found }) + + assert stop_child(queue) == { :error, :not_found } + + assert validate Supervisor + end +end end