channels v0.0.1 Channels.Consumer behaviour
A behaviour module for implementing an AMQP consumer.
A Channels.Consumer is a process that can be used to keep state and provides a standard interface to execute code asynchronously when a message is received from the AMQP broker.
It is based on a GenServer therefore include functionality for tracing and error reporting. It will also fit in a supervision tree.
Example
The Channels.Consumer behaviour abstracts the common broker-consumer interaction. Developers are only required to implement the callbacks and functionality they are interested in.
Let’s start with a code example and then explore the available callbacks. Imagine we want a consumer that receives messages from a queue “my_queue” binded to a fanout exchange “my_exchange”, print the messages and respond with ack:
defmodule Printer do
use Channels.Consumer
def handle_message(payload, _meta, header) do
IO.puts(header <> payload)
{:reply, :ack, header}
end
end
# Exchange and queue config:
config = %{
exchange: %{
name: "my_exchange",
type: "fanout"
},
queue: %{
name: "my_queue"
}
}
# Start the consumer
{:ok, _pid} = Channels.Consumer.start_link(Printer, "Received: ", config)
We start our Printer
by calling start_link/3
, passing the module with
the consumer implementation, its initial state (a header: “Received: “) and
a map configuring the exchange and the queue.
When we start the consumer, the following steps are taking place:
1 - A GenServer is started. 2 - The configured exchange is being declared. 3 - The configured queue is being declared. 4 - The queue is binded to the exchange. 5 - The GenServer is subscribed to the queue.
Imagine the message “Hello world!” is published to “my_exchange”.
handle_message/3
will be called with:
- payload: “Hello world!”
- meta: Metadata sent by the broker plus the adapter and channel the consumer is using.
- header: “Message received: “, the internal state of the consumer.
It will print:
“Message received: Hello world!”
Callbacks
There are 4 callbacks required to be implemented in a Channels.Consumer
.
By adding use Channels.Consumer
to your module, all 6 will be defined,
leaving it up to you to implement the ones you want to customize.
Name Registration
The name registration rules are the same of a GenServer
.
Summary
Functions
Sends an ack to the broker
Sends a nack to the broker. Same behaviour as ack/2
Sends a reject to the broker. Same behaviour as reject/2
Starts a new consumer without links (outside of a supervison tree)
Starts a new consumer server with the given configuration
Callbacks
Invoked to change the state of the Channels.Consumer
when a different version
of a module is loaded (hot code swapping) and the state’s term structure should be
changed
Called when a message is received from the broker
Called when the broker informs that the consumer is subscribed as a consumer and is ready to start processing messages
Called when the consumer is connected to the broker
Called when the consumer exits
Types
Functions
Sends an ack to the broker.
This function is used to explicitly send an ack to the broker
after a message has been received through handle_message/3' when the
ack cannot be sent as the return value of the message handling.
The
metamust be the second argument received in
handle_message/3.
The
opts` argument are options to be given to the underlaying AMQP
adapter.
Always returns :ok.
Sends a nack to the broker. Same behaviour as ack/2
.
Sends a reject to the broker. Same behaviour as reject/2
.
Specs
start(module, initial, config, opts) :: GenServer.on_start
Starts a new consumer without links (outside of a supervison tree).
See start_link4
for more information.
Specs
start_link(module, initial, config, opts) :: GenServer.on_start
Starts a new consumer server with the given configuration.
callback_mod
- The module that implements de behaviour.initial
- The state that will be given to the init/2 callback.config
- The configuration of the consumer.opts
-GenServer
options.
Callbacks
Specs
Invoked to change the state of the Channels.Consumer
when a different version
of a module is loaded (hot code swapping) and the state’s term structure should be
changed.
old_vsn
is the previous version of the module (defined by the @vsn
attribute) when upgrading. When downgrading the previous version is wrapped in
a 2-tuple with first element :down
. state
is the current state of the
GenServer
and extra
is any extra data required to change the state.
Returning {:ok, new_state}
changes the state to new_state
and the code
change is successful.
Returning {:error, reason}
fails the code change with reason reason
and
the state remains as the previous state.
If code_change/3
raises the code change fails and the loop will continue
with its previous state. Therefore this callback does not usually contain side effects.
Called when a message is received from the broker.
If returns {:noreply, state}
the consumer continues normally without
responding the broker (Is expected to ack, nack or reject using the
provided functions (ack/1
, nack/1
and reject/1
) that expect the
meta argument.
If returns {:reply, action, state}
where action is :ack
, :nack
or
:reject
responds to the broker with the given action. If some opts
have to be provided to the adapter (like requeue: false
)
`{:noreply, {action, opts}, state} can also be returned.
If returns {:stop, reason, state} the consumer runs terminate/2 and
then stops with the given reason.
Called when the broker informs that the consumer is subscribed as a consumer and is ready to start processing messages.
If returns {:noreply, state}
the consumer continues normally.
If returns {:stop, reason, state}
the consumer runs terminate/2 and
then stops with the given reason.
Specs
init(initial :: term) :: Init.return_values
Called when the consumer is connected to the broker.
If returns {:ok, state}
the consumer starts waiting for messages.
If returns {:stop, reason}
the consumer is stopped with that reason
without running terminate/2