rabbit_mq v0.0.17 RabbitMQ.Producer behaviour

This module should be used to start a Producer.

Behind the scenes, a dedicated AMQP.Connection is established, and a pool of Producers (workers) is started, resulting in a supervision tree similar to the one below.

Producer supervision tree

Example usage

ℹ️ The following example assumes that the "customer" exchange already exists.

First, define your (ideally domain-specific) Producer:

defmodule RabbitSample.CustomerProducer do
  @moduledoc """
  Publishes pre-configured events onto the "customer" exchange.
  """

  use RabbitMQ.Producer, exchange: "customer", worker_count: 3

  @doc """
  Publishes an event routed via "customer.created".
  """
  def customer_created(customer_id) when is_binary(customer_id) do
    opts = [
      content_type: "application/json",
      correlation_id: UUID.uuid4()
    ]

    payload = Jason.encode!(%{v: "1.0.0", customer_id: customer_id})

    publish(payload, "customer.created", opts)
  end

  @doc """
  Publishes an event routed via "customer.updated".
  """
  def customer_updated(updated_customer) when is_map(updated_customer) do
    opts = [
      content_type: "application/json",
      correlation_id: UUID.uuid4()
    ]

    payload = Jason.encode!(%{v: "1.0.0", customer_data: updated_customer})

    publish(payload, "customer.updated", opts)
  end
end

ℹ️ To see which options can be passed as opts to publish/3, visit https://hexdocs.pm/amqp/AMQP.Basic.html#publish/5.

Then, start as normal under your existing supervision tree:

children = [
  RabbitSample.CustomerProducer
  # ... start other children
]

opts = [strategy: :one_for_one, name: RabbitSample.Supervisor]
Supervisor.start_link(children, opts)

Finally, call the exposed methods from your application:

RabbitSample.CustomerProducer.customer_created(customer_id)
RabbitSample.CustomerProducer.customer_updated(updated_customer)

⚠️ All Producer workers implement "reliable publishing", which means that publisher confirms are always enabled and handled asynchronously, striking a delicate balance between performance and reliability.

To understand why this is important, please refer to the reliable publishing implementation guide.

You can implement the optional handle_publisher_ack_confirms/1 and handle_publisher_nack_confirms/1 callbacks to receive publisher confirmations.

Configuration

The following options can be used with RabbitMQ.Producer;

  • :exchange; messages will be published onto this exchange. Required.
  • :worker_count; number of workers to be spawned. Defaults to 3.

Link to this section Summary

Functions

Returns a specification to start this module under a supervisor.

Sends a :publish message to a worker. Implements round-robin dispatch mechanism.

Retrieves the application-level limit on how many channels can be opened per connection. Can be configured via :rabbit_mq, :max_channels_per_connection.

Starts a named Supervisor, internally managing a dedicated AMQP.Connection as well a dedicated RabbitMQ.Producer.WorkerPool.

Link to this section Types

Link to this type

data()

data() :: String.t()
Link to this type

opts()

opts() :: keyword()
Link to this type

publish_args()

publish_args() :: {routing_key(), data(), opts()}
Link to this type

publish_args_with_seq_no()

publish_args_with_seq_no() :: {seq_no(), routing_key(), data(), opts()}
Link to this type

publish_result()

publish_result() :: {:ok, integer()} | AMQP.Basic.error()
Link to this type

routing_key()

routing_key() :: String.t()
Link to this type

seq_no()

seq_no() :: integer()

Link to this section Functions

Link to this function

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

dispatch(arg, counter, worker, worker_count)

dispatch(publish_args(), module(), module(), integer()) :: publish_result()

Sends a :publish message to a worker. Implements round-robin dispatch mechanism.

Link to this function

max_workers()

max_workers() :: integer()

Retrieves the application-level limit on how many channels can be opened per connection. Can be configured via :rabbit_mq, :max_channels_per_connection.

If not set in config, defaults to 8.

As a rule of thumb, most applications can use a single digit number of channels per connection.

For details, please consult the official RabbitMQ docs: https://www.rabbitmq.com/channels.html#channel-max.

Link to this function

start_link(opts)

start_link(keyword()) :: GenServer.on_start()

Starts a named Supervisor, internally managing a dedicated AMQP.Connection as well a dedicated RabbitMQ.Producer.WorkerPool.

Link to this section Callbacks

Link to this callback

handle_publisher_ack_confirms(list)

(optional)
handle_publisher_ack_confirms([publish_args_with_seq_no()]) :: term()
Link to this callback

handle_publisher_nack_confirms(list)

(optional)
handle_publisher_nack_confirms([publish_args_with_seq_no()]) :: term()
Link to this callback

publish(routing_key, data, opts)

publish(routing_key(), data(), opts()) :: publish_result()