Packages
rambla
0.5.4
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
use DynamicSupervisor
@notify_broadcast Application.get_env(:rambla, :notify_broadcast, true)
case {@notify_broadcast, Code.ensure_compiled(Envio.Publisher)} do
{true, {:module, _}} -> use Envio.Publisher
_ -> defmacrop broadcast(_, _), do: :ok
end
@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))
@spec start_pools :: [DynamicSupervisor.on_start_child()]
def start_pools do
start_pools(
for {k, v} <- Application.get_env(:rambla, :pools, []), do: {fix_type(k), params: v}
)
end
@spec start_pools(%{required(atom()) => keyword()} | keyword()) :: [
DynamicSupervisor.on_start_child()
]
def start_pools(opts) do
Enum.map(opts, fn {type, opts} ->
with {options, opts} <- Keyword.pop(opts, :options, []),
{worker_type, opts} <- Keyword.pop(opts, :type, :local),
{worker_name, opts} <- Keyword.pop(opts, :name, type),
{params, []} <- Keyword.pop(opts, :params, []) do
worker =
Keyword.merge(
options,
name: {worker_type, worker_name},
worker_module: Rambla.Connection
)
child_spec = :poolboy.child_spec(Rambla.Connection, worker, {worker_name, params})
DynamicSupervisor.start_child(Rambla.ConnectionPool, child_spec)
end
end)
end
@spec pools :: [{:undefined, pid() | :restarting, :worker | :supervisor, [:poolboy]}]
def pools, do: DynamicSupervisor.which_children(Rambla.ConnectionPool)
@spec publish(
type :: atom(),
messages :: Rambla.Connection.message() | Rambla.Connection.messages(),
opts :: map()
) ::
Rambla.Connection.outcome() | Rambla.Connection.outcomes()
def publish(type, messages, opts \\ %{})
def publish(type, message, opts) when is_map(message) or is_binary(message) do
case publish(type, [message], opts) do
%{oks: [result], errors: []} -> {:ok, result}
%{oks: [], errors: [reason]} -> {:error, reason}
end
end
def publish(type, messages, opts) when is_list(messages) do
type = fix_type(type)
timeout = messages |> length() |> timeout()
response =
:poolboy.transaction(
type,
&GenServer.call(&1, {:publish, messages, opts}, timeout),
timeout
)
broadcast(type, %{message: messages, response: response})
response
end
@spec conn(type :: atom()) :: any()
def conn(type),
do: type |> fix_type() |> :poolboy.transaction(&GenServer.call(&1, :conn))
@spec fix_type(k :: binary() | atom()) :: module()
defp fix_type(k) when is_binary(k), do: String.to_existing_atom(k)
defp fix_type(k) when is_atom(k) do
case to_string(k) do
"Elixir." <> _ -> k
short_name -> Module.concat("Rambla", Macro.camelize(short_name))
end
end
@spec timeout(count :: non_neg_integer()) :: timeout()
defp timeout(count) when count < 10_000, do: 5_000
defp timeout(count) when count < 20_000, do: 10_000
defp timeout(count) when count < 25_000, do: 15_000
defp timeout(count) when count < 30_000, do: 20_000
defp timeout(_count), do: :infinity
end