AceMQ for Rails
Rails integration for AceMQ over AMQP: one connection for the process, configured the Rails way; consumers written as classes and run in a process of their own; a health check that composes into whatever readiness endpoint the application already has.
It is a thin layer. The library underneath is where publishing, retries, dead-lettering, codecs and the wire contract live, and none of that is rewritten here. What this adds is the four things a Rails application needs and a library cannot supply: a place for configuration, a place for the connection, a process for the consumers, and the executor around a handler that makes ActiveRecord usable from a thread Rails never made.
# config/acemq.yml
shared:
client_name: shop
topology:
exchanges:
- { name: shop-events, type: topic }
queues:
- { name: shop.orders, dead_letter: true }
bindings:
- { queue: shop.orders, exchange: shop-events, routing_key: "order.#" }
production:
url: <%= ENV["ACEMQ_URL"] %># app/controllers/orders_controller.rb
def create
order = Order.create!(order_params)
AceMQ::Rails.publish(order.as_json, to: "order.placed",
exchange: "shop-events", type: "order.placed.v2")
head :created
end# app/consumers/orders_consumer.rb
class OrdersConsumer < AceMQ::Rails::Consumer
queue "shop.orders"
def call(message)
Fulfilment.begin!(message.payload)
accept
end
end$ bundle exec acemq-consumer
That last line is the design, not an implementation detail. Consumers do not run inside Puma, and consumers.md is the argument at length.
Where to go next
| Start here | Getting started |
| Reference | Configuration — every setting |
| Usage | Publishing · Consumers · Topology · Serialization · Testing |
| Security | TLS, credentials, certificates, payload encryption |
| Patterns | From Rails · Outbox · Idempotency · Saga · Request/reply · Scheduling · Streams |
| Operations | Shutdown and the drain · Health · Observability · Interceptors · Eager loading and reloading |
| Design | Why this is not an ActiveJob adapter |
| Support | Enterprise support |
Versions
| Ruby | 3.1 and later |
| Rails | 7.1, 7.2 and 8.x. Rails 8 needs Ruby 3.2, which is Rails' constraint rather than one this gem adds |
acemq-amqp |
~> 0.7.14 — every 0.7.x from 0.7.14, and the next
minor is looked at before it ships here |
| Transport | bunny ~> 2.23, named by the application. The library
declares no runtime dependencies at all |
The constraint on the library is three components on purpose:
~> 0.7 would be pessimistic on the major and
would quietly admit a 0.8 that changed something this gem is written
against. A weekly job checks that the constraint still admits the newest
release, because a constraint that has stopped doing so looks exactly
like one that still does until somebody looks.
What it is not
- Not an ActiveJob adapter, deliberately. not-activejob.md.
- Not a replacement for the library.
AceMQ::Rails.publishis a delegation toAceMQ::AMQP::Connection#publish, and every keyword is the library's. - Not an Engine. No routes, no views, no migrations, nothing to mount.
- Not a scheduler, an outbox or a saga. The library has all three and this gem wraps none of them. patterns.md is how each one is reached from Rails, and which of them needs a process rather than a setting.