Packages
rambla
1.2.5
1.5.0
1.4.2
1.4.1
1.4.0
1.3.0
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.0
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
0.13.0
0.12.2
0.12.1
0.11.1
0.11.0
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Easy publishing to many different targets. Supported back-ends: - Rabbit [Amqp](https://hexdocs.pm/amqp/) - Redis [Redix](https://hexdocs.pm/redix) - Http [:httpc](http://erlang.org/doc/man/httpc.html) - Smtp [:gen_smtp](https://hexdocs.pm/gen_smtp) - Slack [Envío](https://hexdocs.pm/envio)
Current section
Files
Jump to
Current section
Files
lib/rambla/connection_pool.ex
defmodule Rambla.ConnectionPool do
@moduledoc false
@moduledoc deprecated: "Use configuration instead"
use Rambla.Telemetria
use DynamicSupervisor
@spec start_link(opts :: keyword) :: Supervisor.on_start()
def start_link(opts \\ []),
do: DynamicSupervisor.start_link(__MODULE__, opts, name: __MODULE__)
@impl DynamicSupervisor
def init(opts), do: DynamicSupervisor.init(Keyword.put_new(opts, :strategy, :one_for_one))
@mocks Application.compile_env(:rambla, :mocks, %{})
@spec start_pools :: [
[
{:pool, DynamicSupervisor.on_start_child()}
| {:synch, DynamicSupervisor.on_start_child()}
]
]
def start_pools do
pools =
for {k, v} <- Application.get_env(:rambla, :pools, []) do
{options, params} =
:rambla
|> Application.get_env(k, [])
|> Keyword.merge(v)
|> Keyword.pop(:options, [])
{k, [params: params, options: options]}
end
start_pools(pools)
end
@spec start_pools(%{required(atom()) => keyword()} | keyword(), %{optional(atom()) => atom()}) ::
[
[
{:pool, DynamicSupervisor.on_start_child()},
{:synch, DynamicSupervisor.on_start_child()}
]
]
def start_pools(opts, mocks \\ @mocks) do
Enum.map(opts, fn {type, opts} ->
opts =
case opts do
%{} = opts -> Map.to_list(opts)
opts when is_list(opts) -> opts
end
{type, name} = fix_type(type, true, false)
with {options, opts} <- Keyword.pop(opts, :options, []),
{worker_type, opts} <- Keyword.pop(opts, :type, :local),
{params, []} <- Keyword.pop(opts, :params, []) do
module = type_to_module({type, name})
worker =
Keyword.merge(
options,
name: {worker_type, module},
worker_module: Rambla.Connection
)
type = Map.get(mocks, type, type)
child_spec = :poolboy.child_spec(Rambla.Connection, worker, {type, params})
conn_opts =
params
|> Keyword.put(:singleton, Module.concat(module, "Synch"))
|> Keyword.put(:conn_type, type)
[
pool: DynamicSupervisor.start_child(Rambla.ConnectionPool, child_spec),
synch:
DynamicSupervisor.start_child(Rambla.ConnectionPool, {Rambla.Connection, conn_opts})
]
end
end)
end
@spec pools :: [{:undefined, :restarting | pid(), :supervisor | :worker, atom()}]
def pools, do: DynamicSupervisor.which_children(Rambla.ConnectionPool)
@spec publish(
type :: atom() | {atom(), any()},
messages :: Rambla.Connection.message() | Rambla.Connection.messages(),
opts :: map() | keyword()
) ::
Rambla.Connection.outcome() | Rambla.Connection.outcomes()
def publish(type, messages, opts \\ %{})
def publish(type, message, opts) when is_list(opts),
do: publish(type, message, Map.new(opts))
def publish(type, message, opts) when is_map(message) or is_binary(message) do
case do_publish(type, [message], opts) do
%{oks: [result], errors: []} -> {:ok, result}
%{oks: [], errors: [reason]} -> {:error, reason}
other -> other
end
end
def publish(type, messages, opts) when is_list(messages),
do: do_publish(type, messages, opts)
if Rambla.Telemetria.use?(), do: @telemetria(Rambla.Telemetria.apply_options())
@spec do_publish(type :: atom(), messages :: Rambla.Connection.messages(), opts :: map()) ::
Rambla.Connection.outcome() | Rambla.Connection.outcomes()
defp do_publish(type, messages, opts) when is_list(messages) do
timeout = messages |> length() |> timeout()
:poolboy.transaction(
fix_type(type),
&GenServer.call(&1, {:publish, messages, opts}, timeout),
timeout
)
end
@spec publish_synch(
type :: atom(),
messages :: Rambla.Connection.message() | Rambla.Connection.messages(),
opts :: map() | keyword()
) ::
Rambla.Connection.outcome() | Rambla.Connection.outcomes()
def publish_synch(type, message, opts \\ %{})
def publish_synch(type, message, opts) when is_list(opts),
do: publish_synch(type, message, Map.new(opts))
def publish_synch(type, message, %{} = opts),
do: do_publish_synch(type, message, opts)
if Rambla.Telemetria.use?(), do: @telemetria(Rambla.Telemetria.apply_options())
def do_publish_synch(type, message, %{} = opts) do
{timeout, opts} = Map.pop(opts, :gen_server_timeout, 5000)
singleton =
type
|> fix_type()
|> Module.concat("Synch")
GenServer.call(singleton, {:publish, message, opts}, timeout)
end
@spec conn(type :: atom()) :: Rambla.Connection.Config.t()
def conn(type),
do: type |> fix_type() |> :poolboy.transaction(&GenServer.call(&1, :conn))
@spec raw(type :: atom(), (pid() -> any())) :: any()
def raw(type, f) when is_function(f, 1) do
type
|> fix_type()
|> :poolboy.transaction(fn pid ->
case GenServer.call(pid, :conn) do
%Rambla.Connection{conn_pid: pid} -> {:ok, f.(pid)}
_ -> {:error, :connection}
end
end)
end
@spec fix_type(atom() | {atom(), atom() | binary()}, boolean(), boolean()) ::
{module(), any()} | module()
defp fix_type(name, retry? \\ true, module? \\ true)
defp fix_type({type, name}, retry?, module?) when is_atom(type) do
type =
case {retry?, Code.ensure_loaded?(type)} do
{_, true} ->
{type, name}
{true, _} ->
fix_type(type_to_module({"Rambla", type}), false, false)
_ ->
raise Rambla.Exceptions.Unknown,
source: __MODULE__,
reason: "Unknown type: " <> inspect({type, name})
end
if module?, do: type_to_module(type), else: type
end
defp fix_type({type}, retry?, module?) when is_atom(type),
do: fix_type(type, retry?, module?)
defp fix_type(type, retry?, module?) when is_atom(type),
do: fix_type({type, :default}, retry?, module?)
@spec type_to_module({atom(), atom() | binary()} | atom() | binary()) :: module()
defp type_to_module(type) when is_atom(type) or is_binary(type),
do: Module.concat([type |> to_string() |> Macro.camelize()])
defp type_to_module({type, name})
when (is_binary(type) or is_atom(type)) and (is_binary(name) or is_atom(name)),
do: [type, name] |> Enum.map(&type_to_module/1) |> Module.concat()
@spec timeout(count :: non_neg_integer()) :: timeout()
defp timeout(count) when count < 10_000, do: 10_000
defp timeout(count) when count < 20_000, do: 20_000
defp timeout(count) when count < 25_000, do: 25_000
defp timeout(count) when count < 30_000, do: 30_000
defp timeout(_count), do: :infinity
end