View Source RabbitMQStream.Producer behaviour (rabbitmq_stream v0.4.0-rc.2)

RabbitMQStream.Producer allows you to define modules or processes that publish messages to a single stream.

Defining a producer Module

A standalone producer module can be defined with:

defmodule MyApp.MyProducer do
  use RabbitMQStream.Producer,
    stream_name: "my-stream",
    connection: MyApp.MyConnection
end

After adding it to your supervision tree, you can publish messages with:

MyApp.MyProducer.publish("Hello, world!")

You can add the producer to your supervision tree as follows this:

def start(_, _) do
  children = [
    # ...
    MyApp.MyProducer
  ]

  opts = # ...
  Supervisor.start_link(children, opts)
end

The standalone producer starts its own RabbitMQStream.Connection, declaring itself and fetching its most recent publishing_id, and declaring the stream, if it does not exist.

Configuration

The RabbitMQStream.Producer accepts the following options:

  • :stream_name - The name of the stream to publish to. Required.
  • :reference_name - The string which is used by the server to prevent Duplicate Message. Defaults to __MODULE__.Producer.
  • :connection - The identifier for a RabbitMQStream.Connection.
  • :serializer - The module to use to decode the message. Defaults to nil, which means no encoding is done.

You can also declare the configuration in your config.exs:

config :rabbitmq_stream, MyApp.MyProducer,
  stream_name: "my-stream",
  connection: MyApp.MyConnection

Setting up

You can optionally define a before_start/2 callback to perform setup logic, such as creating the stream, if it doesn't yet exists.

defmodule MyApp.MyProducer do
  use RabbitMQStream.Producer,
    stream_name: "my-stream",
    connection: MyApp.MyConnection

  @impl true
  def before_start(_opts, state) do
    # Create the stream
    RabbitMQStream.Connection.create_stream(state.connection, state.stream_name)

    state
  end
end

Configuration

You can configure each Producer with:

config :rabbitmq_stream, MyApp.MyProducer,
  stream_name: "my-stream",
  connection: MyApp.MyConnection

And also you can override the defaults of all producers with:

  config :rabbitmq_stream, :defaults,
    producer: [
      connection: MyApp.MyConnection,
      # ...
    ]
    serializer: Jason

Globally configuring all producers ignores the following options:

  • :stream_name
  • :reference_name

Encoding

You can declare a function for encoding each message by declaring a encode!/1 callback as follows:alarm_handler

defmodule MyApp.MyProducer do
  use RabbitMQStream.Producer,
    stream_name: "my-stream",
    connection: MyApp.MyConnection

  @impl true
  def encode!(message) do
    Jason.encode!(message)
  end
end

Or by passing a :serializer option to the use macro:

defmodule MyApp.MyProducer do
  use RabbitMQStream.Producer,
    stream_name: "my-stream",
    connection: MyApp.MyConnection,
    serializer: Jason
end

The default value for the :serializer is the module itself, unless a default is defined at a higher level of the configuration. If there is a encode!/1 callback defined, it is always used

Summary

Callbacks

Optional callback that is called after the process has started, but before the producer has declared itself and fetched its most recent publishing_id.

Callback responsible for encoding a message into binary format.

Callback responsible for generating the 'filter_value' for a message. The value is used by the Server for filtering the chunks sent to consumer that have defined a 'filter' parameter.

Publishes a single message to the stream.

Types

@type option() ::
  {:stream_name, String.t()}
  | {:reference_name, String.t()}
  | {:connection, GenServer.server()}
@type options() :: [option()]
@type t() :: %RabbitMQStream.Producer{
  connection: GenServer.server(),
  id: String.t() | nil,
  producer_module: module(),
  publishing_id: String.t(),
  reference_name: String.t(),
  sequence: non_neg_integer() | nil,
  stream_name: String.t()
}

Callbacks

Link to this callback

before_start(opts, state)

View Source (optional)
@callback before_start(opts :: options(), state :: t()) :: t()

Optional callback that is called after the process has started, but before the producer has declared itself and fetched its most recent publishing_id.

This is usefull for setup logic, such as creating the Stream if it doesn't yet exists.

@callback encode!(message :: term()) :: binary()

Callback responsible for encoding a message into binary format.

It can be used in many ways, such as to 'Jason.encode!/1' a Map, or to Gzip Compact a message before it is appended to the Stream.

Link to this callback

filter_value(message)

View Source (optional)
@callback filter_value(message :: term()) :: String.t() | nil

Callback responsible for generating the 'filter_value' for a message. The value is used by the Server for filtering the chunks sent to consumer that have defined a 'filter' parameter.

The callback is invoked before the message is encoded, by the serializer options.

Example defintion:

  @impl true
  def filter_value(message) do
    message["key"]
  end
@callback publish(message :: term()) :: :ok

Publishes a single message to the stream.

The message first passes through the 'encode!/1' callback, before being sent to the RabbitMQStream.Producer process responsible for sending the binary message to the Connection.

As of RabbitMQ 3.13.x, the mesagge's 'filter_value' is generated by passing it through the 'filter_value/1' callback.

The callback always returns ':ok', as the server only send a response for a publish in case of an error, in which case the error code is logged.

Functions