Current section
Files
Jump to
Current section
Files
lib/wabbit/basic.ex
defmodule Wabbit.Basic do
@moduledoc """
Functions to publish, consume and acknowledge messages.
"""
require Record
import Wabbit.Record
Record.defrecordp :amqp_msg, [props: p_basic(), payload: ""]
@doc """
Publishes a message to an Exchange.
This method publishes a message to a specific exchange. The message
will be routed to queues as defined by the exchange configuration
and distributed to any subscribers.
The parameter `:exchange` specifies the name of the exchange to
publish to. If set to empty string, it publishes to the default
exchange.
The `:routing_key` parameter specifies the routing key for the
message.
The `:payload` parameter specifies the message content as a binary.
In addition to the previous parameters, the following options can be
used:
# Options
* `:mandatory` - If set, returns an error if the broker can't
route the message to a queue (default `false`)
* `:immediate` - If set, returns an error if the broker can't
deliver te message to a consumer immediately (default `false`)
* `:content_type` - MIME Content type
* `:content_encoding` - MIME Content encoding
* `:headers` - Message headers. Can be used with headers Exchanges
* `:persistent` - If set, uses persistent delivery mode. Messages
marked as `persistent` that are delivered to `durable` queues
will be logged to disk
* `:correlation_id` - application correlation identifier
* `:priority` - message priority, ranging from 0 to 9
* `:reply_to` - name of the reply queue
* `:expiration` - how long the message is valid (in milliseconds)
* `:message_id` - message identifier
* `:timestamp` - timestamp associated with this message (epoch time)
* `:type` - message type as a string
* `:user_id` - creating user ID. RabbitMQ will validate this
against the active connection user
* `:app_id` - publishing application ID
## Examples
iex> Wabbit.Basic.publish channel, \"Hello World!\", exchange: \"my_exchange\", routing_key: \"my_routing_key\", persistent: true
:ok
"""
def publish(channel, payload, options \\ []) do
basic_publish =
basic_publish(exchange: Keyword.get(options, :exchange, ""),
routing_key: Keyword.get(options, :routing_key, ""),
mandatory: Keyword.get(options, :mandatory, false),
immediate: Keyword.get(options, :immediate, false))
p_basic =
p_basic(content_type: Keyword.get(options, :content_type, :undefined),
content_encoding: Keyword.get(options, :content_encoding, :undefined),
headers: Keyword.get(options, :headers, :undefined),
delivery_mode: if(options[:persistent], do: 2, else: 1),
priority: Keyword.get(options, :priority, :undefined),
correlation_id: Keyword.get(options, :correlation_id, :undefined),
reply_to: Keyword.get(options, :reply_to, :undefined),
expiration: Keyword.get(options, :expiration, :undefined),
message_id: Keyword.get(options, :message_id, :undefined),
timestamp: Keyword.get(options, :timestamp, :undefined),
type: Keyword.get(options, :type, :undefined),
user_id: Keyword.get(options, :user_id, :undefined),
app_id: Keyword.get(options, :app_id, :undefined),
cluster_id: Keyword.get(options, :cluster_id, :undefined))
:amqp_channel.cast(channel, basic_publish, amqp_msg(props: p_basic, payload: payload))
end
@doc """
Acknowledges one or more messages.
If `multiple` is set to `true`, all messages up to the one specified
by `delivery_tag` are considered acknowledged by the server.
"""
def ack(channel, delivery_tag, options \\ []) do
:amqp_channel.call(channel,
basic_ack(delivery_tag: delivery_tag,
multiple: Keyword.get(options, :multiple, false)))
end
@doc """
Rejects (and, optionally, requeues) a message.
"""
def reject(channel, delivery_tag, options \\ []) do
:amqp_channel.call(channel,
basic_reject(delivery_tag: delivery_tag,
requeue: Keyword.get(options, :requeue, true)))
end
@doc """
Negative acknowledge of one or more messages.
If `:multiple` is set to `true`, all messages up to the one specified
by `delivery_tag` are considered as not acknowledged by the
server.
If `:requeue` is set to `true`, the message will be returned to the
queue and redelivered to the next available consumer. This is a
RabbitMQ specific extension to AMQP 0.9.1. It is equivalent to
reject, but allows rejecting multiple messages using the `multiple`
option.
"""
def nack(channel, delivery_tag, options \\ []) do
:amqp_channel.call(channel,
basic_nack(delivery_tag: delivery_tag,
multiple: Keyword.get(options, :multiple, false),
requeue: Keyword.get(options, :requeue, true)))
end
@doc """
Registers a queue consumer process.
The `pid` of the process can be set using the `subscriber` argument
and defaults to the calling process.
The consumer process will receive the following messages:
* `{:basic_deliver, payload, meta}` - This is sent for each message
consumed, where `payload` contains the message content and `meta`
contains all the metadata set when sending with Basic.publish or
additional info set by the broker
* `{:basic_consume_ok, %{consumer_tag: consumer_tag}}` - Sent when
the consumer process is registered with Basic.consume. The caller
receives the same information as the return of Basic.consume
* `{:basic_cancel, %{consumer_tag: consumer_tag, no_wait: no_wait}}` - Sent
by the broker when the consumer is unexpectedly cancelled
(such as after a queue deletion)
* `{:basic_cancel_ok, %{consumer_tag: consumer_tag}}` - Sent to the
consumer process after a call to Basic.cancel
# Options
* `:consumer_tag` - Identifier for the consumer, valid within the
current channel
* `:no_local` - If the no-local field is set the server will not
send messages to the connection that published them
* `:no_ack` - If this field is set the server does not expect
acknowledgements for messages
* `:exclusive` - Request exclusive consumer access, meaning only
this consumer can access the queue
* `:no_wait` - If set, the server will not respond to the method
* `:arguments` - A set of arguments for the consume
"""
def consume(channel, queue, options \\ []) do
basic_consume =
basic_consume(
queue: queue,
consumer_tag: Keyword.get(options, :consumer_tag, ""),
no_local: Keyword.get(options, :no_local, false),
no_ack: Keyword.get(options, :no_ack, false),
exclusive: Keyword.get(options, :exclusive, false),
nowait: Keyword.get(options, :no_wait, false),
arguments: Keyword.get(options, :arguments, []))
basic_consume_ok(consumer_tag: consumer_tag) =
:amqp_channel.subscribe(channel, basic_consume, Keyword.get(options, :subscriber, self()))
{:ok, consumer_tag}
end
@doc """
Sets the message prefetch count or size (in bytes).
If `:global` is set to `true` this applies to the entire Connection,
otherwise it applies only to the specified Channel.
# Options
* `:prefetch_size` - Number of messages to be sent in advance
* `:prefetch_count` - Specifies a prefetch window in terms of whole messages
* `:global` - QoS settings scope
"""
def qos(channel, options \\ []) do
basic_qos_ok() = :amqp_channel.call(channel,
basic_qos(
prefetch_size: Keyword.get(options, :prefetch_size, 0),
prefetch_count: Keyword.get(options, :prefetch_count, 0),
global: Keyword.get(options, :global, false)))
:ok
end
end