Packages
rambla
0.9.3
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/connections/amqp.ex
defmodule Rambla.Amqp do
@moduledoc """
Default connection implementation for 🐰 Rabbit.
`publish/2` accepts the following options:
- `exchange` [`binary()`, **mandatory**] the exchange to publish to
- `queue` [`binary()`, **optional**] if passed, the queue will be created
and bound to the exchange; it’s slowing down publishing, but safer
for the cold RebbatMQ installation
- `declare?`[`boolean()`, **optional**, _default_: `true`] if false
is passed, the exchange would not be declared; use it if the exchange
already surely exists to speed up the publishing
- `routing_key` [`binary()`, **optional**, _default_: `""`] if passed,
used as a routing key
- `options` [`keyword()`, **optional**, _default_: `[]`] the options
to be passed as is to call to `AMQP.Basic.publish/5`
---
Since `v0.6.0` provides two `mix` tasks:
- `mix rambla.rabbit.exchange` Operations with exchanges in RabbitMQ
- `mix rambla.rabbit.queue` Operations with queues in RabbitMQ
Tasks support arguments to be passed to RabbitMQ instance. Usage example:
```
mix rambla.rabbit.queue declare foo -o durable:true
```
"""
@with_amqp match?({:module, _}, Code.ensure_compiled(AMQP.Channel))
@behaviour Rambla.Connection
# rabbit = Keyword.get(state, :conn, Application.get_env(:eventory, :amqp, []))
@impl Rambla.Connection
def connect(params) when is_list(params) do
if not @with_amqp or is_nil(params[:host]),
do:
raise(Rambla.Exceptions.Connection,
value: params,
expected: "🐰 configuration with :host key"
)
maybe_amqp(params)
end
@impl Rambla.Connection
def publish(%Rambla.Connection.Config{} = conn, message) when is_binary(message) do
case Jason.decode(message) do
{:ok, term} -> publish(conn, term)
{:error, _} -> do_publish(conn, message)
end
end
@impl Rambla.Connection
def publish(%Rambla.Connection.Config{} = conn, message) when is_list(message),
do: publish(conn, Map.new(message))
@impl Rambla.Connection
def publish(%Rambla.Connection.Config{} = cfg, message)
when is_map(message),
do: do_publish(cfg, message)
@spec do_publish(%Rambla.Connection.Config{}, binary() | map()) ::
{:ok, map()} | {:error, any()}
defp do_publish(%Rambla.Connection.Config{} = cfg, %{} = message),
do: do_publish(cfg, Jason.encode!(message))
defp do_publish(%Rambla.Connection.Config{conn: _conn, chan: chan, opts: opts}, message)
when is_binary(message) do
with %{exchange: exchange} <- opts,
declare? <- Map.get(opts, :declare?, true),
if(declare?, do: apply(AMQP.Exchange, :declare, [chan, exchange])),
:ok <- queue!(chan, opts),
:ok <-
apply(AMQP.Basic, :publish, [
chan,
exchange,
Map.get(opts, :routing_key, ""),
message,
Map.get(opts, :options, [])
]) do
{:ok, message}
else
error -> {:error, error}
end
end
@spec queue!(chan :: AMQP.Channel.t(), map()) :: :ok
defp queue!(chan, %{queue: queue, exchange: exchange}) do
with {:ok, %{consumer_count: _, message_count: _, queue: ^queue}} <-
apply(AMQP.Queue, :declare, [chan, queue]),
do: apply(AMQP.Queue, :bind, [chan, queue, exchange])
end
defp queue!(_, %{exchange: _exchange}), do: :ok
if @with_amqp do
defp maybe_amqp(params) do
with {:ok, conn} <- AMQP.Connection.open(params),
{:ok, chan} <- AMQP.Channel.open(conn) do
%Rambla.Connection{
conn: %Rambla.Connection.Config{conn: conn, chan: chan},
conn_type: __MODULE__,
conn_pid: conn.pid,
conn_params: params,
errors: []
}
else
error ->
%Rambla.Connection{
conn: %Rambla.Connection.Config{},
conn_type: __MODULE__,
conn_pid: nil,
conn_params: params,
errors: [error]
}
end
end
else
defp maybe_amqp(params) do
error =
Rambla.Exceptions.Connection.exception(
source: __MODULE__,
info: params,
reason: "🐰 AMQP should be explicitly included to use this functionality"
)
%Rambla.Connection{
conn: %Rambla.Connection.Config{},
conn_type: __MODULE__,
conn_pid: nil,
conn_params: params,
errors: [error]
}
end
end
end