This guide covers the basics of RabbitMQ plugin development. It is expected that before reading this guide, the reader has a basic understanding of the RabbitMQ plugin mechanism.
Readers are also expected to have a basic understanding of Erlang and the OTP design principles.
Learn You Some Erlang is a great way to get started with Erlang and OTP.
Writing a RabbitMQ plugin provides a number of appealing possibilities:
As with any plugin mechanism, consideration should be given when developing functionality as to whether embedding it as a plugin is the most appropriate path to take. Some reasons that you might not want to develop your functionality as a plugin:
To develop a RabbitMQ plugin, first make sure the following requirements are met:
Erlang.mk is used to build RabbitMQ and its plugins. The easiest way to start on a new plugin is probably to copy an existing plugin such as rabbitmq-metronome, used as an example below.
To test the plugin during development, use the following make target to start a RabbitMQ node with the local plugin built from source and enabled:
make run-broker
A badly-written plugins can pose a risk to the stability of the broker. To ensure that your plugin can safely operate without affecting RabbitMQ core, a couple of safety best practices are highly recommended.
It's possible to specify broker and dependency version requirements for a plugin using the broker_version_requirements key in plugin's application environment. The requirements are specified as a list of minimum version in each release series. Consider the following example:
{application, my_plugin,[ %% ... {broker_version_requirements, ["3.11.15", "3.10.22"]} ]}
The above requires RabbitMQ 3.10.x starting with 3.10.22 and 3.11.x starting with 3.11.15. Note that when new major and minor (feature) RabbitMQ versions come out, it is necessary for plugin maintainers to update the list.
Plugins can have dependencies. It is possible to specify supported version series for dependencies, too. This is quite similar to the above but uses a dictionary-like data structure (proplist).
For example:
{application, my_plugin, [ %% ... {dependency_version_requirements, [{rabbitmq_management, ["3.11.0", "3.10.22"]}]} ]}
means the plugin depends on rabbitmq_management 3.10.x starting with 3.10.22 and all versions in the 3.11.x series.
Seeing as no development guide would be complete without a Hello World example, the following tries to provide the basics of how your would build your very own RabbitMQ plugin.
The following example details how you might build a simple plugin that acts like a metronome.
Every second, it fires a message that has a routing key in the form yyyy.MM.dd.dow.hh.mm.ss to a topic exchange called "metronome" by default. Applications can attach queues to this exchange with various routing keys in order to be invoked at regular intervals. For example, to receive a message every second, a binding of "......" could be applied. To receive a message every minute, a binding of ".....*.00" could be applied instead.
The rabbitmq-metronome repository on GitHub contains a copy of the code for this plugin.
The following table should explain the purpose of the various files in the repository.
Filename | Purpose |
---|---|
Makefile | This top-level Makefile defines the name of your plugin and its dependencies. The name must match the Erlang application name. Dependencies are declared using erlang.mk's variables. Just after that, the Makefile includes rabbitmq-components.mk and erlang.mk, as well as rabbitmq-plugins.mk using erlang.mk plugins facility. See below for a description of those files. |
erlang.mk | A local copy of erlang.mk. This is not a vanilla copy because RabbitMQ relies on a few modifications which have not been merged upstream at the time of this writing. That's why ERLANG_MK_REPO and ERLANG_MK_COMMIT are overridden for now. |
rabbitmq-components.mk |
A local copy of rabbitmq-components.mk. The
original file is in rabbitmq-common which your
plugin will depend on automatically. It contains other
erlang.mk extensions and helpers which must be defined
before erlang.mk inclusion. This file must be
kept up-to-date w.r.t. rabbitmq-common: when it
is out-of-date, you will get the following error:
error: rabbitmq-components.mk must be updated!In this case, just run the following command to update your copy: make rabbitmq-components-mk |
rabbitmq_metronome.schema | A Cuttlefish configuration schema. Used to translate configuration file to the internal format used by RabbitMQ and its runtime. Metronome schema contains mappings for the metronome.exchange setting, setting the exchange used by the plugin. Configuration will be regenerated when the plugin is enabled. Plugin-specific values in the config will cause error if plugin has not been enabled. More information about writing schema files can be found in the Cuttlefish docs. |
src/rabbit_metronome.erl | Implementation of the Erlang "application" behaviour. Provides a means for the Erlang VM to start and stop the plugin. |
src/rabbit_metronome_sup.erl | Implementation of the Erlang "supervisor" behaviour. Monitors the worker process and restarts it if it crashes. |
src/rabbit_metronome_worker.erl | The core of the plugin. The worker will connect internally to the broker, then create a task that will be triggered every second. |
test/metronome_SUITE.erl | Automated tests for the plugin. |
Run make to build the plugin:
make
To start a node with the plugin built and enabled on:
make run-broker
To ensure that the new plugin is up and running, run the following command:
rabbitmq-diagnostics status
If your plugin has loaded successfully, you should see it in the enabled plugin list:
# => Plugins # => # => Enabled plugin file: /var/folders/gp/53t98z011678vk9rkcb_s6ph0000gn/T/rabbitmq-test-instances/rabbit@warp10/enabled_plugins # => Enabled plugins: # => # => * rabbitmq_metronome # => * amqp_client
To run Common Test test suites, use
make tests
Finally, you can produce an .ez file, suitable for distribution with:
DIST_AS_EZS=yes make dist
The file appears in the plugins directory under repository root.
If you have questions about the contents of this guide or any other topic related to RabbitMQ, don't hesitate to ask them using GitHub Discussions or our community Discord server.
If you'd like to contribute an improvement to the site, its source is available on GitHub. Simply fork the repository and submit a pull request. Thank you!