hutch 0.18.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/.travis.yml +20 -8
- data/.yardopts +5 -0
- data/CHANGELOG.md +466 -2
- data/Gemfile +18 -4
- data/Guardfile +13 -4
- data/LICENSE +2 -1
- data/README.md +397 -32
- data/Rakefile +8 -1
- data/bin/ci/before_build.sh +20 -0
- data/bin/ci/install_on_debian.sh +46 -0
- data/hutch.gemspec +6 -7
- data/lib/hutch/acknowledgements/base.rb +16 -0
- data/lib/hutch/acknowledgements/nack_on_all_failures.rb +19 -0
- data/lib/hutch/adapters/march_hare.rb +1 -1
- data/lib/hutch/broker.rb +127 -103
- data/lib/hutch/cli.rb +66 -25
- data/lib/hutch/config.rb +230 -55
- data/lib/hutch/consumer.rb +42 -3
- data/lib/hutch/error_handlers/airbrake.rb +44 -16
- data/lib/hutch/error_handlers/base.rb +15 -0
- data/lib/hutch/error_handlers/bugsnag.rb +30 -0
- data/lib/hutch/error_handlers/honeybadger.rb +33 -18
- data/lib/hutch/error_handlers/logger.rb +12 -6
- data/lib/hutch/error_handlers/rollbar.rb +28 -0
- data/lib/hutch/error_handlers/sentry.rb +15 -12
- data/lib/hutch/error_handlers/sentry_raven.rb +31 -0
- data/lib/hutch/error_handlers.rb +3 -0
- data/lib/hutch/exceptions.rb +8 -1
- data/lib/hutch/logging.rb +5 -5
- data/lib/hutch/message.rb +2 -4
- data/lib/hutch/publisher.rb +75 -0
- data/lib/hutch/serializers/identity.rb +19 -0
- data/lib/hutch/serializers/json.rb +22 -0
- data/lib/hutch/tracers/datadog.rb +17 -0
- data/lib/hutch/tracers.rb +1 -0
- data/lib/hutch/version.rb +1 -2
- data/lib/hutch/waiter.rb +104 -0
- data/lib/hutch/worker.rb +81 -75
- data/lib/hutch.rb +15 -6
- data/lib/yard-settings/handler.rb +38 -0
- data/lib/yard-settings/yard-settings.rb +2 -0
- data/spec/hutch/broker_spec.rb +162 -77
- data/spec/hutch/cli_spec.rb +16 -3
- data/spec/hutch/config_spec.rb +121 -22
- data/spec/hutch/consumer_spec.rb +82 -4
- data/spec/hutch/error_handlers/airbrake_spec.rb +25 -10
- data/spec/hutch/error_handlers/bugsnag_spec.rb +55 -0
- data/spec/hutch/error_handlers/honeybadger_spec.rb +24 -2
- data/spec/hutch/error_handlers/logger_spec.rb +14 -1
- data/spec/hutch/error_handlers/rollbar_spec.rb +45 -0
- data/spec/hutch/error_handlers/sentry_raven_spec.rb +37 -0
- data/spec/hutch/error_handlers/sentry_spec.rb +21 -2
- data/spec/hutch/logger_spec.rb +12 -6
- data/spec/hutch/message_spec.rb +2 -2
- data/spec/hutch/serializers/json_spec.rb +17 -0
- data/spec/hutch/tracers/datadog_spec.rb +44 -0
- data/spec/hutch/waiter_spec.rb +51 -0
- data/spec/hutch/worker_spec.rb +89 -5
- data/spec/spec_helper.rb +7 -5
- data/templates/default/class/html/settings.erb +0 -0
- data/templates/default/class/setup.rb +4 -0
- data/templates/default/fulldoc/html/css/hutch.css +13 -0
- data/templates/default/layout/html/setup.rb +7 -0
- data/templates/default/method_details/html/settings.erb +5 -0
- data/templates/default/method_details/setup.rb +4 -0
- data/templates/default/method_details/text/settings.erb +0 -0
- data/templates/default/module/html/settings.erb +40 -0
- data/templates/default/module/setup.rb +4 -0
- metadata +62 -43
- data/circle.yml +0 -3
data/README.md
CHANGED
@@ -1,24 +1,46 @@
|
|
1
1
|

|
2
2
|
|
3
|
+
[](http://badge.fury.io/rb/hutch)
|
4
|
+
[](https://travis-ci.org/gocardless/hutch)
|
5
|
+
[](https://codeclimate.com/github/gocardless/hutch)
|
6
|
+
|
3
7
|
Hutch is a Ruby library for enabling asynchronous inter-service communication
|
4
8
|
in a service-oriented architecture, using RabbitMQ.
|
5
9
|
|
6
|
-
[](http://badge.fury.io/rb/hutch)
|
7
|
-
[](https://travis-ci.org/gocardless/hutch)
|
8
|
-
[](https://gemnasium.com/gocardless/hutch)
|
9
|
-
[](https://codeclimate.com/github/gocardless/hutch)
|
10
|
-
|
11
10
|
To install with RubyGems:
|
12
11
|
|
13
12
|
```
|
14
|
-
|
13
|
+
gem install hutch
|
15
14
|
```
|
16
15
|
|
17
|
-
|
16
|
+
<!-- Tocer[start]: Auto-generated, don't remove. -->
|
17
|
+
|
18
|
+
### Table of Contents
|
19
|
+
|
20
|
+
- [Requirements](#requirements)
|
21
|
+
- [Overview](#overview)
|
22
|
+
- [Project Maturity](#project-maturity)
|
23
|
+
- [Consumers](#consumers)
|
24
|
+
- [Message Processing Tracers](#message-processing-tracers)
|
25
|
+
- [Running Hutch](#running-hutch)
|
26
|
+
- [Loading Consumers](#loading-consumers)
|
27
|
+
- [Stopping Hutch](#stopping-hutch)
|
28
|
+
- [Producers](#producers)
|
29
|
+
- [Producer Configuration](#producer-configuration)
|
30
|
+
- [Publisher Confirms](#publisher-confirms)
|
31
|
+
- [Writing Well-Behaved Publishers](#writing-well-behaved-publishers)
|
32
|
+
- [Configuration](#configuration)
|
33
|
+
- [Config File](#config-file)
|
34
|
+
- [Environment variables](#environment-variables)
|
35
|
+
- [Configuration precedence](#configuration-precedence)
|
36
|
+
- [Generated list of configuration options](#generated-list-of-configuration-options)
|
18
37
|
|
19
|
-
|
20
|
-
that was extracted from production systems.
|
38
|
+
<!-- Tocer[finish]: Auto-generated, don't remove. -->
|
21
39
|
|
40
|
+
## Requirements
|
41
|
+
|
42
|
+
- Hutch requires Ruby 2.4+ or JRuby 9K.
|
43
|
+
- Hutch requires RabbitMQ 3.3 or later.
|
22
44
|
|
23
45
|
## Overview
|
24
46
|
|
@@ -31,10 +53,16 @@ With Hutch, consumers are stored in separate files and include the `Hutch::Consu
|
|
31
53
|
They are then loaded by a command line runner which connects to RabbitMQ, sets up queues and bindings,
|
32
54
|
and so on. Publishers connect to RabbitMQ via `Hutch.connect` and publish using `Hutch.publish`.
|
33
55
|
|
34
|
-
Hutch uses [Bunny](http://rubybunny.info)
|
56
|
+
Hutch uses [Bunny](http://rubybunny.info) or [March Hare](http://rubymarchhare.info)
|
57
|
+
(on JRuby) under the hood.
|
58
|
+
|
59
|
+
### Project Maturity
|
35
60
|
|
61
|
+
Hutch is a mature project that was originally extracted from production systems
|
62
|
+
at [GoCardless](https://gocardless.com) in 2013 and is now maintained by its contributors
|
63
|
+
and users.
|
36
64
|
|
37
|
-
##
|
65
|
+
## Consumers
|
38
66
|
|
39
67
|
Consumers receive messages from a RabbitMQ queue. That queue may be bound to
|
40
68
|
one or more topics (represented by routing keys).
|
@@ -52,8 +80,8 @@ message[:id] # => "02ABCXYZ"
|
|
52
80
|
To subscribe to a topic, pass a routing key to `consume` in the class
|
53
81
|
definition. To bind to multiple routing keys, simply pass extra routing keys
|
54
82
|
in as additional arguments. Refer to the [RabbitMQ docs on topic exchanges
|
55
|
-
]
|
56
|
-
example consumer:
|
83
|
+
](http://www.rabbitmq.com/tutorials/tutorial-five-ruby.html) for more information
|
84
|
+
about how to use routing keys. Here's an example consumer:
|
57
85
|
|
58
86
|
```ruby
|
59
87
|
class FailedPaymentConsumer
|
@@ -81,6 +109,28 @@ class FailedPaymentConsumer
|
|
81
109
|
end
|
82
110
|
```
|
83
111
|
|
112
|
+
It is possible to set some custom options to consumer's queue explicitly.
|
113
|
+
This example sets the consumer's queue as a
|
114
|
+
[quorum queue](https://www.rabbitmq.com/quorum-queues.html)
|
115
|
+
and to operate in the [lazy mode](https://www.rabbitmq.com/lazy-queues.html).
|
116
|
+
The `initial_group_size`
|
117
|
+
[argument](https://www.rabbitmq.com/quorum-queues.html#replication-factor) is
|
118
|
+
optional.
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
class FailedPaymentConsumer
|
122
|
+
include Hutch::Consumer
|
123
|
+
consume 'gc.ps.payment.failed'
|
124
|
+
queue_name 'failed_payments'
|
125
|
+
lazy_queue
|
126
|
+
quorum_queue initial_group_size: 3
|
127
|
+
|
128
|
+
def process(message)
|
129
|
+
mark_payment_as_failed(message[:id])
|
130
|
+
end
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
84
134
|
You can also set custom arguments per consumer. This example declares a consumer with
|
85
135
|
a maximum length of 10 messages:
|
86
136
|
|
@@ -92,7 +142,9 @@ class FailedPaymentConsumer
|
|
92
142
|
end
|
93
143
|
```
|
94
144
|
|
95
|
-
|
145
|
+
This sets the `x-max-length` header. For more details, see the [RabbitMQ
|
146
|
+
documentation on Queue Length Limit](https://www.rabbitmq.com/maxlength.html). To find out more
|
147
|
+
about custom queue arguments, consult the [RabbitMQ documentation on AMQP Protocol Extensions](https://www.rabbitmq.com/extensions.html).
|
96
148
|
|
97
149
|
Consumers can write to Hutch's log by calling the logger method. The logger method returns
|
98
150
|
a [Logger object](http://ruby-doc.org/stdlib-2.1.2/libdoc/logger/rdoc/Logger.html).
|
@@ -101,7 +153,7 @@ a [Logger object](http://ruby-doc.org/stdlib-2.1.2/libdoc/logger/rdoc/Logger.htm
|
|
101
153
|
class FailedPaymentConsumer
|
102
154
|
include Hutch::Consumer
|
103
155
|
consume 'gc.ps.payment.failed'
|
104
|
-
|
156
|
+
|
105
157
|
def process(message)
|
106
158
|
logger.info "Marking payment #{message[:id]} as failed"
|
107
159
|
mark_payment_as_failed(message[:id])
|
@@ -130,11 +182,19 @@ to learn more.
|
|
130
182
|
|
131
183
|
Tracers allow you to track message processing.
|
132
184
|
|
133
|
-
|
185
|
+
This will enable NewRelic custom instrumentation:
|
186
|
+
|
134
187
|
```ruby
|
135
188
|
Hutch::Config.set(:tracer, Hutch::Tracers::NewRelic)
|
136
189
|
```
|
137
|
-
|
190
|
+
|
191
|
+
And this will enable Datadog custom instrumentation:
|
192
|
+
|
193
|
+
```ruby
|
194
|
+
Hutch::Config.set(:tracer, Hutch::Tracers::Datadog)
|
195
|
+
```
|
196
|
+
|
197
|
+
Batteries included!
|
138
198
|
|
139
199
|
## Running Hutch
|
140
200
|
|
@@ -187,13 +247,55 @@ directory of a Rails app, or pass the path to a Rails app in with the
|
|
187
247
|
the `app/consumers/` directory, to allow them to be auto-loaded when Rails
|
188
248
|
boots.
|
189
249
|
|
250
|
+
If you're using the new Zeitwerk autoloader (enabled by default in Rails 6)
|
251
|
+
and the consumers are not loaded in development environment you will need to
|
252
|
+
trigger the autoloading in an initializer with
|
253
|
+
|
254
|
+
```ruby
|
255
|
+
::Zeitwerk::Loader.eager_load_all
|
256
|
+
```
|
257
|
+
|
258
|
+
or with something more specific like
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
autoloader = Rails.autoloaders.main
|
262
|
+
|
263
|
+
Dir.glob(File.join('app/consumers', '*_consumer.rb')).each do |consumer|
|
264
|
+
autoloader.preload(consumer)
|
265
|
+
end
|
266
|
+
```
|
267
|
+
|
268
|
+
### Consumer Groups
|
269
|
+
|
270
|
+
It is possible to load only a subset of consumers. This is done by defining a consumer
|
271
|
+
group under the `consumer_groups` configuration key:
|
272
|
+
|
273
|
+
``` yaml
|
274
|
+
consumer_groups:
|
275
|
+
payments:
|
276
|
+
- DepositConsumer
|
277
|
+
- CashoutConsumer
|
278
|
+
notification:
|
279
|
+
- EmailNotificationConsumer
|
280
|
+
```
|
281
|
+
|
282
|
+
To only load a group of consumers, use the `--only-group` option:
|
283
|
+
|
284
|
+
``` shell
|
285
|
+
hutch --only-group=payments --config=/path/to/hutch.yaml
|
286
|
+
```
|
287
|
+
|
288
|
+
### Loading Consumers Manually (One-by-One)
|
289
|
+
|
190
290
|
To require files that define consumers manually, simply pass each file as an
|
191
291
|
option to `--require`. Hutch will automatically detect whether you've provided
|
192
292
|
a Rails app or a standard file, and take the appropriate behaviour:
|
193
293
|
|
194
294
|
```bash
|
195
|
-
|
196
|
-
|
295
|
+
# loads a rails app
|
296
|
+
hutch --require path/to/rails-app
|
297
|
+
# loads a ruby file
|
298
|
+
hutch --require path/to/file.rb
|
197
299
|
```
|
198
300
|
|
199
301
|
### Stopping Hutch
|
@@ -270,10 +372,10 @@ AMQP.connect(host: config[:host]) do |connection|
|
|
270
372
|
end
|
271
373
|
```
|
272
374
|
|
273
|
-
If using publisher confirms with amqp gem, see [this issue]
|
274
|
-
and [this gist]
|
375
|
+
If using publisher confirms with amqp gem, see [this issue](https://github.com/ruby-amqp/amqp/issues/92)
|
376
|
+
and [this gist](https://gist.github.com/3042381) for more info.
|
275
377
|
|
276
|
-
## Configuration
|
378
|
+
## Configuration
|
277
379
|
|
278
380
|
### Config File
|
279
381
|
|
@@ -289,6 +391,8 @@ Known configuration parameters are:
|
|
289
391
|
* `mq_tls`: should TLS be used? (default: `false`)
|
290
392
|
* `mq_tls_cert`: path to client TLS certificate (public key)
|
291
393
|
* `mq_tls_key`: path to client TLS private key
|
394
|
+
* `mq_tls_ca_certificates`: array of paths to CA keys (if not specified to Hutch, will default to Bunny defaults which are system-dependent)
|
395
|
+
* `mq_verify_peer`: should SSL certificate be verified? (default: `true`)
|
292
396
|
* `require_paths`: array of paths to require
|
293
397
|
* `autoload_rails`: should Hutch command line runner try to automatically load Rails environment files?
|
294
398
|
* `daemonise`: should Hutch runner process daemonise?
|
@@ -298,18 +402,279 @@ Known configuration parameters are:
|
|
298
402
|
tracked (e.g. using `Hutch::Broker#confirm_select` callback or `Hutch::Broker#wait_for_confirms`)
|
299
403
|
* `force_publisher_confirms`: enables publisher confirms, forces `Hutch::Broker#wait_for_confirms` for every publish. **This is the safest option which also offers the lowest throughput**.
|
300
404
|
* `log_level`: log level used by the standard Ruby logger (default: `Logger::INFO`)
|
405
|
+
* `error_handlers`: a list of error handler objects, see classes in `Hutch::ErrorHandlers`. All configured
|
406
|
+
handlers will be invoked unconditionally in the order listed.
|
407
|
+
* `error_acknowledgements`: a chain of responsibility of objects that acknowledge/reject/requeue messages when an
|
408
|
+
exception happens, see classes in `Hutch::Acknowledgements`.
|
301
409
|
* `mq_exchange`: exchange to use for publishing (default: `hutch`)
|
302
410
|
* `heartbeat`: [RabbitMQ heartbeat timeout](http://rabbitmq.com/heartbeats.html) (default: `30`)
|
303
411
|
* `connection_timeout`: Bunny's socket open timeout (default: `11`)
|
304
412
|
* `read_timeout`: Bunny's socket read timeout (default: `11`)
|
305
|
-
* `
|
413
|
+
* `write_timeout`: Bunny's socket write timeout (default: `11`)
|
414
|
+
* `automatically_recover`: Bunny's enable/disable network recovery (default: `true`)
|
415
|
+
* `network_recovery_interval`: Bunny's reconnect interval (default: `1`)
|
306
416
|
* `tracer`: tracer to use to track message processing
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
417
|
+
* `namespace`: A namespace string to help group your queues (default: `nil`)
|
418
|
+
|
419
|
+
### Environment variables
|
420
|
+
|
421
|
+
The file configuration options mentioned above can also be passed in via environment variables, using the `HUTCH_` prefix, eg.
|
422
|
+
|
423
|
+
* `connection_timeout` → `HUTCH_CONNECTION_TIMEOUT`.
|
424
|
+
|
425
|
+
### Configuration precedence
|
426
|
+
|
427
|
+
In order from lowest to highest precedence:
|
428
|
+
|
429
|
+
0. Default values
|
430
|
+
0. `HUTCH_*` environment variables
|
431
|
+
0. Configuration file
|
432
|
+
0. Explicit settings through `Hutch::Config.set`
|
433
|
+
|
434
|
+
### Generated list of configuration options
|
435
|
+
|
436
|
+
Generate with
|
437
|
+
|
438
|
+
0. `yard doc lib/hutch/config.rb`
|
439
|
+
0. Copy the _Configuration_ section from `doc/Hutch/Config.html` here, with the anchor tags stripped.
|
440
|
+
|
441
|
+
<table border="1" class="settings" style="overflow:visible;">
|
442
|
+
<thead>
|
443
|
+
<tr>
|
444
|
+
<th>
|
445
|
+
Setting name
|
446
|
+
</th>
|
447
|
+
<th>
|
448
|
+
Default value
|
449
|
+
</th>
|
450
|
+
<th>
|
451
|
+
Type
|
452
|
+
</th>
|
453
|
+
<th>
|
454
|
+
ENV variable
|
455
|
+
</th>
|
456
|
+
<th>
|
457
|
+
Description
|
458
|
+
</th>
|
459
|
+
</tr>
|
460
|
+
</thead>
|
461
|
+
<tbody>
|
462
|
+
<tr>
|
463
|
+
<td><tt>mq_host</tt></td>
|
464
|
+
<td>127.0.0.1</td>
|
465
|
+
<td>String</td>
|
466
|
+
<td><tt>HUTCH_MQ_HOST</tt></td>
|
467
|
+
<td><p>RabbitMQ hostname</p></td>
|
468
|
+
</tr>
|
469
|
+
<tr>
|
470
|
+
<td><tt>mq_exchange</tt></td>
|
471
|
+
<td>hutch</td>
|
472
|
+
<td>String</td>
|
473
|
+
<td><tt>HUTCH_MQ_EXCHANGE</tt></td>
|
474
|
+
<td><p>RabbitMQ Exchange to use for publishing</p></td>
|
475
|
+
</tr>
|
476
|
+
<tr>
|
477
|
+
<td><tt>mq_exchange_type</tt></td>
|
478
|
+
<td>topic</td>
|
479
|
+
<td>String</td>
|
480
|
+
<td><tt>HUTCH_MQ_EXCHANGE_TYPE</tt></td>
|
481
|
+
<td><p>RabbitMQ Exchange type to use for publishing</p></td>
|
482
|
+
</tr>
|
483
|
+
<tr>
|
484
|
+
<td><tt>mq_vhost</tt></td>
|
485
|
+
<td>/</td>
|
486
|
+
<td>String</td>
|
487
|
+
<td><tt>HUTCH_MQ_VHOST</tt></td>
|
488
|
+
<td><p>RabbitMQ vhost to use</p></td>
|
489
|
+
</tr>
|
490
|
+
<tr>
|
491
|
+
<td><tt>mq_username</tt></td>
|
492
|
+
<td>guest</td>
|
493
|
+
<td>String</td>
|
494
|
+
<td><tt>HUTCH_MQ_USERNAME</tt></td>
|
495
|
+
<td><p>RabbitMQ username to use.</p></td>
|
496
|
+
</tr>
|
497
|
+
<tr>
|
498
|
+
<td><tt>mq_password</tt></td>
|
499
|
+
<td>guest</td>
|
500
|
+
<td>String</td>
|
501
|
+
<td><tt>HUTCH_MQ_PASSWORD</tt></td>
|
502
|
+
<td><p>RabbitMQ password</p></td>
|
503
|
+
</tr>
|
504
|
+
<tr>
|
505
|
+
<td><tt>uri</tt></td>
|
506
|
+
<td>nil</td>
|
507
|
+
<td>String</td>
|
508
|
+
<td><tt>HUTCH_URI</tt></td>
|
509
|
+
<td><p>RabbitMQ URI (takes precedence over MQ username, password, host, port and vhost settings)</p></td>
|
510
|
+
</tr>
|
511
|
+
<tr>
|
512
|
+
<td><tt>mq_api_host</tt></td>
|
513
|
+
<td>127.0.0.1</td>
|
514
|
+
<td>String</td>
|
515
|
+
<td><tt>HUTCH_MQ_API_HOST</tt></td>
|
516
|
+
<td><p>RabbitMQ HTTP API hostname</p></td>
|
517
|
+
</tr>
|
518
|
+
<tr>
|
519
|
+
<td><tt>mq_port</tt></td>
|
520
|
+
<td>5672</td>
|
521
|
+
<td>Number</td>
|
522
|
+
<td><tt>HUTCH_MQ_PORT</tt></td>
|
523
|
+
<td><p>RabbitMQ port</p></td>
|
524
|
+
</tr>
|
525
|
+
<tr>
|
526
|
+
<td><tt>mq_api_port</tt></td>
|
527
|
+
<td>15672</td>
|
528
|
+
<td>Number</td>
|
529
|
+
<td><tt>HUTCH_MQ_API_PORT</tt></td>
|
530
|
+
<td><p>RabbitMQ HTTP API port</p></td>
|
531
|
+
</tr>
|
532
|
+
<tr>
|
533
|
+
<td><tt>heartbeat</tt></td>
|
534
|
+
<td>30</td>
|
535
|
+
<td>Number</td>
|
536
|
+
<td><tt>HUTCH_HEARTBEAT</tt></td>
|
537
|
+
<td><p><a href="http://rabbitmq.com/heartbeats.html">RabbitMQ heartbeat timeout</a></p></td>
|
538
|
+
</tr>
|
539
|
+
<tr>
|
540
|
+
<td><tt>channel_prefetch</tt></td>
|
541
|
+
<td>0</td>
|
542
|
+
<td>Number</td>
|
543
|
+
<td><tt>HUTCH_CHANNEL_PREFETCH</tt></td>
|
544
|
+
<td><p>The <tt>basic.qos</tt> prefetch value to use.</p></td>
|
545
|
+
</tr>
|
546
|
+
<tr>
|
547
|
+
<td><tt>connection_timeout</tt></td>
|
548
|
+
<td>11</td>
|
549
|
+
<td>Number</td>
|
550
|
+
<td><tt>HUTCH_CONNECTION_TIMEOUT</tt></td>
|
551
|
+
<td><p>Bunny's socket open timeout</p></td>
|
552
|
+
</tr>
|
553
|
+
<tr>
|
554
|
+
<td><tt>read_timeout</tt></td>
|
555
|
+
<td>11</td>
|
556
|
+
<td>Number</td>
|
557
|
+
<td><tt>HUTCH_READ_TIMEOUT</tt></td>
|
558
|
+
<td><p>Bunny's socket read timeout</p></td>
|
559
|
+
</tr>
|
560
|
+
<tr>
|
561
|
+
<td><tt>write_timeout</tt></td>
|
562
|
+
<td>11</td>
|
563
|
+
<td>Number</td>
|
564
|
+
<td><tt>HUTCH_WRITE_TIMEOUT</tt></td>
|
565
|
+
<td><p>Bunny's socket write timeout</p></td>
|
566
|
+
</tr>
|
567
|
+
<tr>
|
568
|
+
<td><tt>automatically_recover</tt></td>
|
569
|
+
<td>true</td>
|
570
|
+
<td>Boolean</td>
|
571
|
+
<td><tt>HUTCH_AUTOMATICALLY_RECOVER</tt></td>
|
572
|
+
<td><p>Bunny's enable/disable network recovery</p></td>
|
573
|
+
</tr>
|
574
|
+
<tr>
|
575
|
+
<td><tt>network_recovery_interval</tt></td>
|
576
|
+
<td>1</td>
|
577
|
+
<td>Number</td>
|
578
|
+
<td><tt>HUTCH_NETWORK_RECOVERY_INTERVAL</tt></td>
|
579
|
+
<td><p>Bunny's reconnect interval</p></td>
|
580
|
+
</tr>
|
581
|
+
<tr>
|
582
|
+
<td><tt>graceful_exit_timeout</tt></td>
|
583
|
+
<td>11</td>
|
584
|
+
<td>Number</td>
|
585
|
+
<td><tt>HUTCH_GRACEFUL_EXIT_TIMEOUT</tt></td>
|
586
|
+
<td><p>FIXME: DOCUMENT THIS</p></td>
|
587
|
+
</tr>
|
588
|
+
<tr>
|
589
|
+
<td><tt>consumer_pool_size</tt></td>
|
590
|
+
<td>1</td>
|
591
|
+
<td>Number</td>
|
592
|
+
<td><tt>HUTCH_CONSUMER_POOL_SIZE</tt></td>
|
593
|
+
<td><p>Bunny consumer work pool size</p></td>
|
594
|
+
</tr>
|
595
|
+
<tr>
|
596
|
+
<td><tt>mq_tls</tt></td>
|
597
|
+
<td>false</td>
|
598
|
+
<td>Boolean</td>
|
599
|
+
<td><tt>HUTCH_MQ_TLS</tt></td>
|
600
|
+
<td><p>Should TLS be used?</p></td>
|
601
|
+
</tr>
|
602
|
+
<tr>
|
603
|
+
<td><tt>mq_verify_peer</tt></td>
|
604
|
+
<td>true</td>
|
605
|
+
<td>Boolean</td>
|
606
|
+
<td><tt>HUTCH_MQ_VERIFY_PEER</tt></td>
|
607
|
+
<td><p>Should SSL certificate be verified?</p></td>
|
608
|
+
</tr>
|
609
|
+
<tr>
|
610
|
+
<td><tt>mq_api_ssl</tt></td>
|
611
|
+
<td>false</td>
|
612
|
+
<td>Boolean</td>
|
613
|
+
<td><tt>HUTCH_MQ_API_SSL</tt></td>
|
614
|
+
<td><p>Should SSL be used for the RabbitMQ API?</p></td>
|
615
|
+
</tr>
|
616
|
+
<tr>
|
617
|
+
<td><tt>autoload_rails</tt></td>
|
618
|
+
<td>true</td>
|
619
|
+
<td>Boolean</td>
|
620
|
+
<td><tt>HUTCH_AUTOLOAD_RAILS</tt></td>
|
621
|
+
<td><p>Should the current Rails app directory be required?</p></td>
|
622
|
+
</tr>
|
623
|
+
<tr>
|
624
|
+
<td><tt>daemonise</tt></td>
|
625
|
+
<td>false</td>
|
626
|
+
<td>Boolean</td>
|
627
|
+
<td><tt>HUTCH_DAEMONISE</tt></td>
|
628
|
+
<td><p>Should the Hutch runner process daemonise?</p></td>
|
629
|
+
</tr>
|
630
|
+
<tr>
|
631
|
+
<td><tt>publisher_confirms</tt></td>
|
632
|
+
<td>false</td>
|
633
|
+
<td>Boolean</td>
|
634
|
+
<td><tt>HUTCH_PUBLISHER_CONFIRMS</tt></td>
|
635
|
+
<td><p>Should RabbitMQ publisher confirms be enabled?</p></td>
|
636
|
+
</tr>
|
637
|
+
<tr>
|
638
|
+
<td><tt>force_publisher_confirms</tt></td>
|
639
|
+
<td>false</td>
|
640
|
+
<td>Boolean</td>
|
641
|
+
<td><tt>HUTCH_FORCE_PUBLISHER_CONFIRMS</tt></td>
|
642
|
+
<td><p>Enables publisher confirms, forces Hutch::Broker#wait_for_confirms for</p></td>
|
643
|
+
</tr>
|
644
|
+
<tr>
|
645
|
+
<td><tt>enable_http_api_use</tt></td>
|
646
|
+
<td>true</td>
|
647
|
+
<td>Boolean</td>
|
648
|
+
<td><tt>HUTCH_ENABLE_HTTP_API_USE</tt></td>
|
649
|
+
<td><p>Should the RabbitMQ HTTP API be used?</p></td>
|
650
|
+
</tr>
|
651
|
+
<tr>
|
652
|
+
<td><tt>consumer_pool_abort_on_exception</tt></td>
|
653
|
+
<td>false</td>
|
654
|
+
<td>Boolean</td>
|
655
|
+
<td><tt>HUTCH_CONSUMER_POOL_ABORT_ON_EXCEPTION</tt></td>
|
656
|
+
<td><p>Should Bunny's consumer work pool threads abort on exception.</p></td>
|
657
|
+
</tr>
|
658
|
+
<tr>
|
659
|
+
<td><tt>consumer_tag_prefix</tt></td>
|
660
|
+
<td>hutch</td>
|
661
|
+
<td>String</td>
|
662
|
+
<td><tt>HUTCH_CONSUMER_TAG_PREFIX</tt></td>
|
663
|
+
<td><p>Prefix displayed on the consumers tags.</p></td>
|
664
|
+
</tr>
|
665
|
+
<tr>
|
666
|
+
<td><tt>namespace</tt></td>
|
667
|
+
<td>nil</td>
|
668
|
+
<td>String</td>
|
669
|
+
<td><tt>HUTCH_NAMESPACE</tt></td>
|
670
|
+
<td><p>A namespace to help group your queues</p></td>
|
671
|
+
</tr>
|
672
|
+
<tr>
|
673
|
+
<td><tt>group</tt></td>
|
674
|
+
<td>''</td>
|
675
|
+
<td>String</td>
|
676
|
+
<td><tt>HUTCH_GROUP</tt></td>
|
677
|
+
<td></td>
|
678
|
+
</tr>
|
679
|
+
</tbody>
|
680
|
+
</table>
|
data/Rakefile
CHANGED
@@ -11,4 +11,11 @@ RSpec::Core::RakeTask.new(:spec) do |t|
|
|
11
11
|
t.rspec_opts = %w(--color --format doc)
|
12
12
|
end
|
13
13
|
|
14
|
-
task :
|
14
|
+
task default: :spec
|
15
|
+
|
16
|
+
#
|
17
|
+
# Re-generate API docs
|
18
|
+
#
|
19
|
+
require 'yard'
|
20
|
+
require 'yard/rake/yardoc_task'
|
21
|
+
YARD::Rake::YardocTask.new
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env sh
|
2
|
+
|
3
|
+
CTL=${BUNNY_RABBITMQCTL:-"sudo rabbitmqctl"}
|
4
|
+
PLUGINS=${BUNNY_RABBITMQ_PLUGINS:-"sudo rabbitmq-plugins"}
|
5
|
+
|
6
|
+
echo "Will use rabbitmqctl at ${CTL}"
|
7
|
+
echo "Will use rabbitmq-plugins at ${PLUGINS}"
|
8
|
+
|
9
|
+
$PLUGINS enable rabbitmq_management
|
10
|
+
|
11
|
+
sleep 3
|
12
|
+
|
13
|
+
# guest:guest has full access to /
|
14
|
+
$CTL add_vhost /
|
15
|
+
$CTL add_user guest guest
|
16
|
+
$CTL set_permissions -p / guest ".*" ".*" ".*"
|
17
|
+
|
18
|
+
# Reduce retention policy for faster publishing of stats
|
19
|
+
$CTL eval 'supervisor2:terminate_child(rabbit_mgmt_sup_sup, rabbit_mgmt_sup), application:set_env(rabbitmq_management, sample_retention_policies, [{global, [{605, 1}]}, {basic, [{605, 1}]}, {detailed, [{10, 1}]}]), rabbit_mgmt_sup_sup:start_child().' || true
|
20
|
+
$CTL eval 'supervisor2:terminate_child(rabbit_mgmt_agent_sup_sup, rabbit_mgmt_agent_sup), application:set_env(rabbitmq_management_agent, sample_retention_policies, [{global, [{605, 1}]}, {basic, [{605, 1}]}, {detailed, [{10, 1}]}]), rabbit_mgmt_agent_sup_sup:start_child().' || true
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
sudo apt-get install curl gnupg debian-keyring debian-archive-keyring apt-transport-https -y
|
4
|
+
|
5
|
+
## Team RabbitMQ's main signing key
|
6
|
+
sudo apt-key adv --keyserver "hkps://keys.openpgp.org" --recv-keys "0x0A9AF2115F4687BD29803A206B73A36E6026DFCA"
|
7
|
+
## Launchpad PPA that provides modern Erlang releases
|
8
|
+
sudo apt-key adv --keyserver "keyserver.ubuntu.com" --recv-keys "F77F1EDA57EBB1CC"
|
9
|
+
## PackageCloud RabbitMQ repository
|
10
|
+
sudo apt-key adv --keyserver "keyserver.ubuntu.com" --recv-keys "F6609E60DC62814E"
|
11
|
+
|
12
|
+
## Add apt repositories maintained by Team RabbitMQ
|
13
|
+
sudo tee /etc/apt/sources.list.d/rabbitmq.list <<EOF
|
14
|
+
## Provides modern Erlang/OTP releases
|
15
|
+
##
|
16
|
+
## "bionic" as distribution name should work for any reasonably recent Ubuntu or Debian release.
|
17
|
+
## See the release to distribution mapping table in RabbitMQ doc guides to learn more.
|
18
|
+
deb http://ppa.launchpad.net/rabbitmq/rabbitmq-erlang/ubuntu bionic main
|
19
|
+
deb-src http://ppa.launchpad.net/rabbitmq/rabbitmq-erlang/ubuntu bionic main
|
20
|
+
|
21
|
+
## Provides RabbitMQ
|
22
|
+
##
|
23
|
+
## "bionic" as distribution name should work for any reasonably recent Ubuntu or Debian release.
|
24
|
+
## See the release to distribution mapping table in RabbitMQ doc guides to learn more.
|
25
|
+
deb https://packagecloud.io/rabbitmq/rabbitmq-server/ubuntu/ bionic main
|
26
|
+
deb-src https://packagecloud.io/rabbitmq/rabbitmq-server/ubuntu/ bionic main
|
27
|
+
EOF
|
28
|
+
|
29
|
+
## Update package indices
|
30
|
+
sudo apt-get update -y
|
31
|
+
|
32
|
+
## Install Erlang packages
|
33
|
+
sudo apt-get install -y erlang-base \
|
34
|
+
erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets \
|
35
|
+
erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key \
|
36
|
+
erlang-runtime-tools erlang-snmp erlang-ssl \
|
37
|
+
erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl
|
38
|
+
|
39
|
+
## Install rabbitmq-server and its dependencies
|
40
|
+
sudo apt-get install rabbitmq-server -y --fix-missing
|
41
|
+
|
42
|
+
sudo service rabbitmq-server start
|
43
|
+
|
44
|
+
sudo rabbitmqctl await_startup --timeout 120
|
45
|
+
|
46
|
+
until sudo lsof -i:5672; do echo "Waiting for RabbitMQ to start..."; sleep 1; done
|
data/hutch.gemspec
CHANGED
@@ -3,22 +3,21 @@ require File.expand_path('../lib/hutch/version', __FILE__)
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
4
|
if defined?(JRUBY_VERSION)
|
5
5
|
gem.platform = 'java'
|
6
|
-
gem.add_runtime_dependency 'march_hare', '>=
|
6
|
+
gem.add_runtime_dependency 'march_hare', '>= 3.0.0'
|
7
7
|
else
|
8
8
|
gem.platform = Gem::Platform::RUBY
|
9
|
-
gem.add_runtime_dependency 'bunny', '>=
|
9
|
+
gem.add_runtime_dependency 'bunny', '>= 2.16', '< 3.0'
|
10
10
|
end
|
11
11
|
gem.add_runtime_dependency 'carrot-top', '~> 0.0.7'
|
12
|
-
gem.add_runtime_dependency 'multi_json', '~> 1.
|
13
|
-
gem.add_runtime_dependency 'activesupport', '>=
|
14
|
-
gem.add_development_dependency 'rspec', '~> 3.0'
|
15
|
-
gem.add_development_dependency 'simplecov', '~> 0.7.1'
|
12
|
+
gem.add_runtime_dependency 'multi_json', '~> 1.14'
|
13
|
+
gem.add_runtime_dependency 'activesupport', '>= 4.2', '< 7'
|
16
14
|
|
17
15
|
gem.name = 'hutch'
|
18
16
|
gem.summary = 'Easy inter-service communication using RabbitMQ.'
|
19
|
-
gem.description = 'Hutch is a Ruby library for enabling asynchronous '
|
17
|
+
gem.description = 'Hutch is a Ruby library for enabling asynchronous ' \
|
20
18
|
'inter-service communication using RabbitMQ.'
|
21
19
|
gem.version = Hutch::VERSION.dup
|
20
|
+
gem.required_ruby_version = '>= 2.2'
|
22
21
|
gem.authors = ['Harry Marr']
|
23
22
|
gem.email = ['developers@gocardless.com']
|
24
23
|
gem.homepage = 'https://github.com/gocardless/hutch'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Hutch
|
2
|
+
module Acknowledgements
|
3
|
+
# Defines acknowledgement handler interface.
|
4
|
+
class Base
|
5
|
+
# Implements negative acknowledgement/requeueing logic
|
6
|
+
# and returns a boolean to indicate whether acknowledgement
|
7
|
+
# was performed. If false is returned, next handler in the
|
8
|
+
# chain will be invoked.
|
9
|
+
#
|
10
|
+
# The chain always falls back to unconditional nacking.
|
11
|
+
def handle(delivery_info, properties, broker, ex)
|
12
|
+
raise NotImplementedError.new
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'hutch/logging'
|
2
|
+
require 'hutch/acknowledgements/base'
|
3
|
+
|
4
|
+
module Hutch
|
5
|
+
module Acknowledgements
|
6
|
+
class NackOnAllFailures < Base
|
7
|
+
include Logging
|
8
|
+
|
9
|
+
def handle(delivery_info, properties, broker, ex)
|
10
|
+
prefix = "message(#{properties.message_id || '-'}): "
|
11
|
+
logger.debug "#{prefix} nacking message"
|
12
|
+
|
13
|
+
broker.nack(delivery_info.delivery_tag)
|
14
|
+
|
15
|
+
true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|