Hutch
A system for processing messages from RabbitMQ.
Install / Use
/learn @ruby-amqp/HutchREADME

Hutch is a Ruby library for enabling asynchronous inter-service communication in a service-oriented architecture, using RabbitMQ.
To install with RubyGems:
gem install hutch
<!-- Tocer[start]: Auto-generated, don't remove. -->
Table of Contents
<!-- Tocer[finish]: Auto-generated, don't remove. -->Requirements
- Hutch requires Ruby 2.4+ or JRuby 9K.
- Hutch requires RabbitMQ 3.3 or later.
Overview
Hutch is a conventions-based framework for writing services that communicate over RabbitMQ. Hutch is opinionated: it uses topic exchanges for message distribution and makes some assumptions about how consumers and publishers should work.
With Hutch, consumers are stored in separate files and include the Hutch::Consumer module.
They are then loaded by a command line runner which connects to RabbitMQ, sets up queues and bindings,
and so on. Publishers connect to RabbitMQ via Hutch.connect and publish using Hutch.publish.
Hutch uses Bunny or March Hare (on JRuby) under the hood.
Project Maturity
Hutch is a mature project that was originally extracted from production systems at GoCardless in 2013 and is now maintained by its contributors and users.
Consumers
Consumers receive messages from a RabbitMQ queue. That queue may be bound to one or more topics (represented by routing keys).
To create a consumer, include the Hutch::Consumer module in a class that
defines a #process method. #process should take a single argument, which
will be a Message object. The Message object encapsulates the message data,
along with any associated metadata. To access properties of the message, use
Hash-style indexing syntax:
message[:id] # => "02ABCXYZ"
To subscribe to a topic, pass a routing key to consume in the class
definition. To bind to multiple routing keys, simply pass extra routing keys
in as additional arguments. Refer to the RabbitMQ docs on topic exchanges
for more information
about how to use routing keys. Here's an example consumer:
class FailedPaymentConsumer
include Hutch::Consumer
consume 'gc.ps.payment.failed'
def process(message)
mark_payment_as_failed(message[:id])
end
end
By default, the queue name will be named using the consumer class. You can set
the queue name explicitly by using the queue_name method:
class FailedPaymentConsumer
include Hutch::Consumer
consume 'gc.ps.payment.failed'
queue_name 'failed_payments'
def process(message)
mark_payment_as_failed(message[:id])
end
end
It is possible to set some custom options to consumer's queue explicitly.
This example sets the consumer's queue as a
quorum queue
and to operate in the lazy mode.
The initial_group_size
argument is
optional.
class FailedPaymentConsumer
include Hutch::Consumer
consume 'gc.ps.payment.failed'
queue_name 'failed_payments'
lazy_queue
quorum_queue initial_group_size: 3
def process(message)
mark_payment_as_failed(message[:id])
end
end
You can also set custom arguments per consumer. This example declares a consumer with a maximum length of 10 messages:
class FailedPaymentConsumer
include Hutch::Consumer
consume 'gc.ps.payment.failed'
arguments 'x-max-length' => 10
end
This sets the x-max-length header. For more details, see the RabbitMQ
documentation on Queue Length Limit. To find out more
about custom queue arguments, consult the RabbitMQ documentation on AMQP Protocol Extensions.
Consumers can write to Hutch's log by calling the logger method. The logger method returns a Logger object.
class FailedPaymentConsumer
include Hutch::Consumer
consume 'gc.ps.payment.failed'
def process(message)
logger.info "Marking payment #{message[:id]} as failed"
mark_payment_as_failed(message[:id])
end
end
If you are using Hutch with Rails and want to make Hutch log to the Rails
logger rather than stdout, add this to config/initializers/hutch.rb
Hutch::Logging.logger = Rails.logger
A logger can be set for the client by adding this config before calling Hutch.connect
client_logger = Logger.new("/path/to/bunny.log")
Hutch::Config.set(:client_logger, client_logger)
See this RabbitMQ tutorial on topic exchanges to learn more.
Message Processing Tracers
Tracers allow you to track message processing.
This will enable NewRelic custom instrumentation:
Hutch::Config.set(:tracer, Hutch::Tracers::NewRelic)
And this will enable Datadog custom instrumentation:
Hutch::Config.set(:tracer, Hutch::Tracers::Datadog)
Batteries included!
Running Hutch
After installing the Hutch gem, you should be able to start it by simply
running hutch on the command line. hutch takes a number of options:
$ hutch -h
usage: hutch [options]
--mq-host HOST Set the RabbitMQ host
--mq-port PORT Set the RabbitMQ port
-t, --[no-]mq-tls Use TLS for the AMQP connection
--mq-tls-cert FILE Certificate for TLS client verification
--mq-tls-key FILE Private key for TLS client verification
--mq-exchange EXCHANGE Set the RabbitMQ exchange
--mq-vhost VHOST Set the RabbitMQ vhost
--mq-username USERNAME Set the RabbitMQ username
--mq-password PASSWORD Set the RabbitMQ password
--mq-api-host HOST Set the RabbitMQ API host
--mq-api-port PORT Set the RabbitMQ API port
-s, --[no-]mq-api-ssl Use SSL for the RabbitMQ API
--config FILE Load Hutch configuration from a file
--require PATH Require a Rails app or path
--[no-]autoload-rails Require the current rails app directory
-q, --quiet Quiet logging
-v, --verbose Verbose logging
--version Print the version and exit
-h, --help Show this message and exit
The first three are for configuring which RabbitMQ instance to connect to.
--require is covered in the next section. Configurations can also be
specified in a YAML file for convenience by passing the file location
to the --config option. The file should look like:
mq_username: peter
mq_password: rabbit
mq_host: broker.yourhost.com
Passing a setting as a command-line option will overwrite what's specified in the config file, allowing for easy customization.
Loading Consumers
Using Hutch with a Rails app is simple. Either start Hutch in the working
directory of a Rails app, or pass the path to a Rails app in with the
--require option. Consumers defined in Rails apps should be placed with in
the app/consumers/ directory, to allow them to be auto-loaded when Rails
boots.
If you're using the new Zeitwerk autoloader (enabled by default in Rails 6) and the consumers are not loaded in development environment you will need to trigger the autoloading in an initializer with
::Zeitwerk::Loader.eager_load_all
or with something more specific like
autoloader = Rails.autoloaders.main
Dir.glob(File.join('app/consumers', '*_consumer.rb')).each do |consumer|
autoloader.preload(consumer)
end
Consumer Groups
It is possible to load only a subset of consumers. This is done by defining a consumer
group under the consumer_groups configuration key:
consumer_groups:
payments:
- DepositConsumer
- CashoutConsumer
notification:
- EmailNotificationConsumer
To only load a group of consumers, use the --only-group option:
hutch --only-group=payments --config=/path/to/hutch.yaml
Loading Consumers Manually (One-by-One)
To require files that define consumers manually, simply pass each file as an
option to --require. Hutch will automatically detect whether you've provided
a Rails app or a standard file, and take the appropriate behaviour:
# loads a rails app
hutch --require path/to/rails-app
# loads a ruby file
hutch --require path/to/file.rb
Stopping Hutch
Hutch supports graceful stops. That means that if done correctly, Hutch will wait for your consumer to finish processing before exiting.
To gracefully stop your workers, you may send the following signals to your Hutch processes: INT, TERM, or QUIT.
Related Skills
node-connect
350.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
110.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
350.8kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
350.8kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
