diff --git a/lib/application.ex b/lib/application.ex deleted file mode 100644 index 6599e6a..0000000 --- a/lib/application.ex +++ /dev/null @@ -1,14 +0,0 @@ -defmodule Kadabra.Application do - @moduledoc false - - use Application - - def start(_type, _args) do - children = [ - {Registry, keys: :unique, name: Registry.Kadabra}, - {Task.Supervisor, name: Kadabra.Tasks} - ] - - Supervisor.start_link(children, strategy: :one_for_one, name: :kadabra) - end -end diff --git a/lib/connection_supervisor.ex b/lib/connection_supervisor.ex new file mode 100644 index 0000000..7635a5e --- /dev/null +++ b/lib/connection_supervisor.ex @@ -0,0 +1,24 @@ +defmodule Kadabra.ConnectionSupervisor do + @moduledoc false + + use DynamicSupervisor + + def start_link(args) do + instance_name = Keyword.fetch!(args, :instance_name) + DynamicSupervisor.start_link(__MODULE__, nil, name: name(instance_name)) + end + + @impl true + def init(_init_arg) do + DynamicSupervisor.init(strategy: :one_for_one) + end + + def start_child(instance_name, opts) do + spec = {Kadabra.ConnectionPool, opts} + DynamicSupervisor.start_child(name(instance_name), spec) + end + + defp name(instance_name) do + :"Kadabra.ConnectionSupervisor.#{instance_name}" + end +end diff --git a/lib/kadabra.ex b/lib/kadabra.ex index 10b4558..f3e3ba2 100644 --- a/lib/kadabra.ex +++ b/lib/kadabra.ex @@ -92,6 +92,8 @@ defmodule Kadabra do @type uri :: charlist | String.t() + @type instance_name :: atom() + @doc ~S""" Opens a new connection. @@ -109,17 +111,22 @@ defmodule Kadabra do def open(uri, opts \\ []) def open(uri, opts) when is_binary(uri) do + open(:kadabra, uri, opts) + end + + def open(uri, opts) when is_list(uri) do + uri |> to_string() |> open(opts) + end + + @spec open(instance_name, uri, conn_opts) :: {:ok, pid} | {:error, term} + def open(instance_name, uri, opts) when is_binary(uri) do pool_opts = [ uri: URI.parse(uri), pid: self(), opts: opts ] - Supervisor.start_child(:kadabra, {Kadabra.ConnectionPool, pool_opts}) - end - - def open(uri, opts) when is_list(uri) do - uri |> to_string() |> open(opts) + Kadabra.ConnectionSupervisor.start_child(instance_name, pool_opts) end @doc ~S""" diff --git a/lib/supervisor.ex b/lib/supervisor.ex new file mode 100644 index 0000000..cafff38 --- /dev/null +++ b/lib/supervisor.ex @@ -0,0 +1,36 @@ +defmodule Kadabra.Supervisor do + @moduledoc ~S""" + Supervisor to be used by the library user to add it to the desired supervision tree. + This allows the library user to be more in control of how failures are managed. + When using this, you probably don't want the Kadabra Application to be started. + You can accomplish this by specifying in your dependency: + + ```elixir + {:kadabra, app: false} + ``` + + You can add this to your supervision tree with the following spec: + + ```elixir + {Kadabra.Supervisor, name: :custom_kadabra_supervisor} + ``` + """ + + use Supervisor + + def start_link(args) do + name = Keyword.fetch!(args, :name) + Supervisor.start_link(__MODULE__, name, name: :"Kadabra.Supervisor.#{name}") + end + + @impl true + def init(name) do + children = [ + {Registry, keys: :unique, name: Registry.Kadabra}, + {Task.Supervisor, name: Kadabra.Tasks}, + {Kadabra.ConnectionSupervisor, instance_name: name} + ] + + Supervisor.init(children, strategy: :one_for_one) + end +end diff --git a/mix.exs b/mix.exs index dbf7cb8..4f30c0b 100644 --- a/mix.exs +++ b/mix.exs @@ -31,8 +31,7 @@ defmodule Kadabra.Mixfile do def application do [ - extra_applications: [:logger, :ssl], - mod: {Kadabra.Application, []} + extra_applications: [:logger, :ssl] ] end