Go to file
David Ansari bf84ea4aa1 Support filters in quorum queues
## What?

Support for quorum queues:
* JMS message selectors
* AMQP property filter expressions on header and properties
  sections (as already supported in streams)
* message groups

 ## How?

* performance tests of different PoCs on
  https://github.com/ansd/message_selector_perf
* Message selector feature is enabled statically on the QQ via queue arg x-filter-enabled=true
* QQ holds application-properties and a subset of well defined fields of
  the header and properties sections in memory. The latter are defined
  by x-(filter-field-names).
* JMS spec: “For best performance, applications should only use message properties when they
  need to customize a message’s header. The primary reason for doing this is to support
  customized message selection.”
  Thefore it should be fine for the session to always include all application-properties
  in the Ra enqueue command.
* In the enqueue{} Ra command, provide a #{Key => Value} map
  * If the Key is atom(), it is a well defined header or properties field name
  * If the Key is binary(), it is an (arbitrary) application-properties key
* filter-field-names policy change takes effect for senders of new sessions
* For high prio or normal prio messages, instead of rabbit_fifo_q we use
  gb_trees
* each QQ consumer remembers its last scanned Ra index and continues
  scanning where it left off previously
* Ideally we need a skip list instead of gb_trees because it's simple, avoids O(n)
  rebalance, and could even append in O(1). However, this cannot be implemented in
  Erlang. A NIF would be one solution, but isn't interoperable.
* gb_trees rebalancing should be acceptable given that emitting all Ra live
  indexes requires O(N) space anyway
* Use another gb_trees for prompt message expiry
* Add/recommend limits for
  * max consumers per queue
  * max messages per queue
  * max metadata size per message
  The latter two provide an overall limit on memory usage.
* Round robin isn't guaranteed in all cases. However, this should be
  okay because JMS doesn't define how a broker should dispatch messages:
  > "Apart from the requirements of any message selectors, Jakarta
  Messaging does not define how messages are distributed between multiple
  consumers on the same queue."
* rabbit_quorum_queue parses the consumer arg JMS SQL expression.
  This way, it’s easy to create consumers with SQL expressions for AMQP 0.9.1 or STOMP, in addition to AMQP 1.0.
  Maybe prohibit though?
* JMS SQL expressions and grammar is declared declaraively
* leex is used to scan the SQL string into a flat structure of tokens.
* yecc parses this flat list of tokens into an Erlang expression tree,
  which is then provided to the QQ in the Ra #checkout{} command.
* QQ then does the simple matching logic by taking the already parsed
  SQL String (similar to module sjx_evaluator) and a map of keys to values.
* We keep the JMS selector matching and AMQP filter expression matching
  separate since they are both sufficiently simple.
* This keeps the state machine simple because both parsing of the SQL
  expression for the consumer and parsing the mc message fields for the
  enqueuer are both done outside the state machine.
* To keep the state machine deterministic, regexes are avoided for SQL 'LIKE'
  expressions. From OTP 28 release notes:
  "It is worth noting that the internal format produced by re:compile/2 has
  changed in Erlang/OTP 28. It cannot be reused across nodes or OTP versions."
  Holding compiled regexes in rabbit_fifo state is problematic because
 the snapshot can be sent to another node running a different OTP version.
* Support for quorum queues the same AMQP property filter expressions as
  for streams, that is application-properties and properties sections,
  i.e. the bare message headers.
  1. annotations (delivery-annotations, message-annotations, footer sections)
     can have complex types which makes filtering more complex
  2. filter expressions for streams support only properties and application-properties
  3. all JMS Headers and JMS Properties are mapped to one of AMQP header, properties,
     application-properties sections because JMS property values can only be simple types

TODOs:
* new Ra state machine version
* Add some configurable limit for max metadata size per message to hold in memory.
  Could be configured by x-filter-max-in-memory-bytes-per-msg.
  rabbit_fifo_client could then estimate the memory overhead can directly reject the message if too large.
  Keeps the state machine simple.
  Rejecting the message is fast.
  Saves resources: no need to write it too the log.
2025-06-04 18:51:54 +02:00
.github CI: tweak OCI build triggers 2025-05-13 11:10:19 +01:00
deps Support filters in quorum queues 2025-06-04 18:51:54 +02:00
doc Add files to specify license info 2020-08-18 12:42:43 -07:00
mk Use Erlang.mk's native Elixir support for CLI 2025-03-18 10:02:49 +01:00
packaging Use Erlang.mk's native Elixir support for CLI 2025-03-18 10:02:49 +01:00
release-notes Mention AMQP durable field in 4.2 release notes 2025-05-20 08:32:52 +02:00
scripts Remove Bazel files 2025-03-13 13:42:34 +00:00
selenium Fix issue related to popup warning 2025-05-22 10:08:22 +02:00
.dockerignore dockerignore deps 2021-03-18 15:04:39 +00:00
.elp.toml Add configuration for ELP language server 2024-05-16 11:10:40 +02:00
.git-blame-ignore-revs Add #13008 to .git-blame-ignore-revs 2025-01-02 12:08:04 -05:00
.gitignore Adds rabbit_auth_backend_internal_loopback 2025-04-09 12:53:29 -07:00
.mailmap Add .mailmap file 2023-11-03 13:17:30 +01:00
CODE_OF_CONDUCT.md Replace @rabbitmq.com addresses with rabbitmq-core@groups.vmware.com 2023-06-20 15:40:13 +04:00
COMMUNITY_SUPPORT.md Update COMMUNITY_SUPPORT.md 2024-12-03 11:03:34 -05:00
CONTRIBUTING.md Document RABBITMQ_METADATA_STORE in CONTRIBUTING.md 2024-12-19 17:40:34 -05:00
LICENSE Replace @rabbitmq.com addresses with rabbitmq-core@groups.vmware.com 2023-06-20 15:40:13 +04:00
LICENSE-APACHE2 (c) year bumps 2024-01-01 22:02:20 -05:00
LICENSE-MPL-RabbitMQ Revert drop of Exhibit B on MPL 2.0 2020-07-20 17:03:37 +01:00
Makefile Adds rabbit_auth_backend_internal_loopback 2025-04-09 12:53:29 -07:00
PKG_LINUX.md URL Cleanup 2019-03-20 03:22:38 -05:00
PKG_WINDOWS.md Windows doc tweaks 2018-11-08 13:48:46 -08:00
README.md Support AMQP over WebSocket (OSS part) 2025-01-27 17:50:47 +01:00
SERVER_RELEASES.md Update SERVER_RELEASES.md 2025-02-10 14:16:51 -05:00
erlang.mk Update Erlang.mk 2025-03-20 15:24:05 +01:00
erlang_ls.config erlang_ls: Add 'deps/*/' to include dirs 2024-04-12 09:49:34 -04:00
plugins.mk Adds rabbit_auth_backend_internal_loopback 2025-04-09 12:53:29 -07:00
rabbitmq-components.mk Merge pull request #13913 from rabbitmq/mk-ra-2.16.9 2025-05-19 08:11:21 +04:00
rebar.config Revert "Format MQTT code with `erlfmt`" 2023-01-27 18:25:57 +00:00

README.md

Test

RabbitMQ Server

RabbitMQ is a feature rich, multi-protocol messaging and streaming broker. It supports:

Installation

Tutorials and Documentation

Some key doc guides include

RabbitMQ documentation is also developed on GitHub.

Commercial Features and Support

Getting Help from the Community

Please read the Community Support Eligibility Policy document first.

The recommended community forums are

Contributing

See CONTRIBUTING.md and our development process overview.

Questions about contributing, internals and so on are very welcome in GitHub Discussions or community Discord server in the core-and-plugin-dev channel.

Licensing

RabbitMQ server is licensed under the MPL 2.0.

Community Support Eligibility Policy document explains the open source RabbitMQ support policy adopted by the RabbitMQ Core Team.

Building From Source and Packaging

(c) 2007-2025 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.