Current section
Files
Jump to
Current section
Files
lib/clover.ex
defmodule Clover do
@moduledoc """
Documentation for Clover.
"""
use Application
@registry Clover.Registry
@robot_supervisor Clover.Robots
def start(_type, _args) do
Clover.Supervisor.start_link(@robot_supervisor, name: Clover.App)
end
def start_supervised_robot(name, mod, adapter, opts \\ [])
def start_supervised_robot(name, mod, adapter, opts) when is_atom(adapter) do
start_supervised_robot(name, mod, {adapter, []}, opts)
end
def start_supervised_robot(name, mod, {adapter, adapter_opts}, opts) do
start_opts = Keyword.take(opts, [:timeout, :debug, :spawn_opt])
DynamicSupervisor.start_child(
@robot_supervisor,
Clover.Robot.Supervisor.child_spec({name, mod, {adapter, adapter_opts}}, start_opts)
)
end
@spec stop_supervised_robot(String.t()) :: :ok | {:error, :not_found}
def stop_supervised_robot(robot) do
case whereis_robot_supervisor(robot) do
nil -> :ok
pid -> DynamicSupervisor.terminate_child(@robot_supervisor, pid)
end
end
@doc """
Start a robot outside of the `Clover` supervision tree.
The robot's pid will still be registered in the `Clover` registry, but the processes will not be
supervised by `Clover`, and you can manage link the robot into your own supervision tree. Returns
the `pid` of the robot's supervisor.
To stop the robot, call `Supervisor.stop(pid)`.
"""
def start_robot(name, mod, adapter, opts \\ [])
def start_robot(name, mod, {adapter, adapter_opts}, opts) do
start_opts = Keyword.take(opts, [:timeout, :debug, :spawn_opt])
Clover.Robot.Supervisor.start_link({name, mod, {adapter, adapter_opts}}, start_opts)
end
def registry, do: @registry
def whereis_robot(robot) do
case Registry.lookup(@registry, robot) do
[{pid, _}] -> pid
[] -> nil
end
end
def whereis_robot_adapter(robot) do
case Registry.lookup(@registry, {robot, :adapter}) do
[{pid, _}] -> pid
[] -> nil
end
end
defp whereis_robot_supervisor(robot) do
case whereis_robot(robot) do
nil ->
nil
pid ->
@robot_supervisor
|> DynamicSupervisor.which_children()
|> find_supervisor_for_robot(pid)
end
end
defp find_supervisor_for_robot(supervisors, robot_pid) do
supervisors
|> Enum.find(fn child ->
child
|> child_pid()
|> Supervisor.which_children()
|> Enum.find(fn child -> child_pid(child) == robot_pid end)
end)
|> case do
nil -> nil
child -> child_pid(child)
end
end
defp child_pid({_, pid, _, _}), do: pid
def format_error({:not_exported, {mod, function}}) do
"#{mod} does not export function #{function}"
end
def format_error({:badarg, {mod, function, arg}}) do
"bad argument for #{mod}.#{function}: #{arg}"
end
def format_error(reason) do
reason
end
end