hutch 0.10.0 → 0.11.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 +4 -4
- data/CHANGELOG.md +61 -2
- data/README.md +57 -9
- data/hutch.gemspec +1 -1
- data/lib/hutch.rb +7 -0
- data/lib/hutch/broker.rb +21 -1
- data/lib/hutch/config.rb +11 -1
- data/lib/hutch/version.rb +1 -1
- data/lib/hutch/worker.rb +1 -1
- data/spec/hutch/broker_spec.rb +34 -0
- data/spec/hutch/worker_spec.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4ae8b34c445db665d717e7c4b935ae246c793c4
|
4
|
+
data.tar.gz: d92e37a658a7a46a08500cf7c14589f7f6df2a17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 149952fbd91217d9bb7a92c7eac65607b45af0b35aaf0bba3424996376fa0f49fd205efc02b67e5b6a7f7a7a66a1dd22ad0e35ad576772905b0d91dc9da62950
|
7
|
+
data.tar.gz: 6a128089af08c252778bf0cef44cfbbc522aea4938c7a4904c9ea74e21528fc13559a3ecb5011700c36a4e87bdd9b98e171593a3e28829312d3b9162c9774d7e
|
data/CHANGELOG.md
CHANGED
@@ -1,14 +1,73 @@
|
|
1
|
-
## 0.
|
1
|
+
## 0.11.0 — unreleased
|
2
|
+
|
3
|
+
### Publisher Confirms Support
|
4
|
+
|
5
|
+
`:force_publisher_confirms` is a new configuration option that forces `Hutch.publish` to wait
|
6
|
+
for a confirm for every message published. Note that this **will cause a significant drop in throughput**.
|
7
|
+
|
8
|
+
`Hutch::Broker#confirm_select` and `Hutch::Broker#wait_for_confirms` are new public API methods
|
9
|
+
that delegate to their respective `Bunny::Channel` counterparts. `Hutch::Broker#confirm_select`
|
10
|
+
can be used to handle confirms with a callback instead of waiting:
|
11
|
+
|
12
|
+
``` ruby
|
13
|
+
broker.confirm_select do |delivery_tag, multiple, nack|
|
14
|
+
# ...
|
15
|
+
end
|
16
|
+
```
|
17
|
+
|
2
18
|
|
3
19
|
### Bunny Update
|
4
20
|
|
5
|
-
Bunny is updated to
|
21
|
+
Bunny is updated to [1.6.0](http://blog.rubyrabbitmq.info/blog/2014/10/31/bunny-1-dot-6-0-is-released/).
|
22
|
+
|
23
|
+
|
24
|
+
## 0.10.0 — Oct 22, 2014
|
25
|
+
|
26
|
+
### Configuration via URI
|
27
|
+
|
28
|
+
Hutch now supports a new configuration key, `:uri`, which allows
|
29
|
+
connection configuration via a URI.
|
30
|
+
|
31
|
+
Note that since the URI has to include credentials, this option
|
32
|
+
is not available on the command line.
|
33
|
+
|
34
|
+
### Bunny Update
|
35
|
+
|
36
|
+
Bunny is updated to `1.5.1`, which mitigates the POODLE attack
|
37
|
+
by disabling SSL 3.0 where possible.
|
38
|
+
|
39
|
+
### Payload in Error Handlers
|
40
|
+
|
41
|
+
Error handlers will now have access to message payload.
|
42
|
+
|
43
|
+
Contributed by Daniel Farrell.
|
6
44
|
|
7
45
|
### Exceptions in Error Handlers Don't Prevent Nacks
|
8
46
|
|
9
47
|
Exceptions in error handlers no longer prevent messages from being
|
10
48
|
`basic.nack`-ed.
|
11
49
|
|
50
|
+
### Pid File Support
|
51
|
+
|
52
|
+
`:pidfile` is a new configuration option that stores Hutch process
|
53
|
+
PID in a file at provided path.
|
54
|
+
|
55
|
+
Contributed by Rustam Sharshenov.
|
56
|
+
|
57
|
+
### More Info on Message
|
58
|
+
|
59
|
+
Bunny's `delivery_info`, `properties` and payload are now accessible on `Hutch::Message`.
|
60
|
+
|
61
|
+
Contributed by gregory.
|
62
|
+
|
63
|
+
|
64
|
+
### Optional Config Parameters
|
65
|
+
|
66
|
+
`Hutch::Config` constructor now accepts an extra hash of optional
|
67
|
+
configuration parameters.
|
68
|
+
|
69
|
+
Contributed by Ignazio Mostallino.
|
70
|
+
|
12
71
|
|
13
72
|
## 0.9.0 — May 13, 2014
|
14
73
|
|
data/README.md
CHANGED
@@ -26,6 +26,10 @@ over RabbitMQ. Hutch is opinionated: it uses topic exchanges for message
|
|
26
26
|
distribution and makes some assumptions about how consumers and publishers
|
27
27
|
should work.
|
28
28
|
|
29
|
+
With Hutch, consumers are stored in separate files and include the `Hutch::Consumer` module.
|
30
|
+
They are then loaded by a command line runner which connects to RabbitMQ, sets up queues and bindings,
|
31
|
+
and so on. Publishers connect to RabbitMQ via `Hutch.connect` and publish using `Hutch.publish`.
|
32
|
+
|
29
33
|
Hutch uses [Bunny](http://rubybunny.info) under the hood.
|
30
34
|
|
31
35
|
|
@@ -160,6 +164,26 @@ Hutch.connect
|
|
160
164
|
Hutch.publish('routing.key', subject: 'payment', action: 'received')
|
161
165
|
```
|
162
166
|
|
167
|
+
### Producer Configuration
|
168
|
+
|
169
|
+
Producers are not run with the 'hutch' command. You can specify configuration
|
170
|
+
options as follows:
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
Hutch::Config.set(:mq_exchange, 'name')
|
174
|
+
```
|
175
|
+
|
176
|
+
### Publisher Confirms
|
177
|
+
|
178
|
+
For maximum message reliability when producing messages, you can force Hutch to use
|
179
|
+
[Publisher Confirms](https://www.rabbitmq.com/confirms.html) and wait for a confirmation
|
180
|
+
after every message published. This is the safest possible option for publishers
|
181
|
+
but also results in a **significant throughput drop**.
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
Hutch::Config.set(:force_publisher_confirms, true)
|
185
|
+
```
|
186
|
+
|
163
187
|
### Writing Well-Behaved Publishers
|
164
188
|
|
165
189
|
You may need to send messages to Hutch from languages other than Ruby. This
|
@@ -174,11 +198,8 @@ send messages to Hutch.
|
|
174
198
|
- Use message routing keys that match those used in your Hutch consumers.
|
175
199
|
- Be sure your exchanges are marked as durable. In the Ruby AMQP gem, this is
|
176
200
|
done by passing `durable: true` to the exchange creation method.
|
177
|
-
-
|
178
|
-
|
179
|
-
- Wrapping publishing code in transactions or using publisher confirms is
|
180
|
-
highly recommended. This can be slightly tricky, see [this issue][pc-issue]
|
181
|
-
and [this gist][pc-gist] for more info.
|
201
|
+
- Publish messages as persistent.
|
202
|
+
- Using publisher confirms is highly recommended.
|
182
203
|
|
183
204
|
Here's an example of a well-behaved publisher, minus publisher confirms:
|
184
205
|
|
@@ -192,15 +213,42 @@ AMQP.connect(host: config[:host]) do |connection|
|
|
192
213
|
end
|
193
214
|
```
|
194
215
|
|
216
|
+
If using publisher confirms with amqp gem, see [this issue][pc-issue]
|
217
|
+
and [this gist][pc-gist] for more info.
|
218
|
+
|
219
|
+
## Configuration Reference
|
220
|
+
|
221
|
+
### Config File
|
222
|
+
|
223
|
+
It is recommended to use a separate config file, unless you use URIs for connection (see below).
|
224
|
+
|
225
|
+
Known configuration parameters are:
|
226
|
+
|
227
|
+
* `mq_host`: RabbitMQ hostname (default: `localhost`)
|
228
|
+
* `mq_port`: RabbitMQ port (default: `5672`)
|
229
|
+
* `mq_vhost`: vhost to use (default: `/`)
|
230
|
+
* `mq_username`: username to use (default: `guest`, only can connect from localhost as of RabbitMQ 3.3.0)
|
231
|
+
* `mq_password`: password to use (default: `guest`)
|
232
|
+
* `mq_tls`: should TLS be used? (default: `false`)
|
233
|
+
* `mq_tls_cert`: path to client TLS certificate (public key)
|
234
|
+
* `mq_tls_key`: path to client TLS private key
|
235
|
+
* `require_paths`: array of paths to require
|
236
|
+
* `autoload_rails`: should Hutch command line runner try to automatically load Rails environment files?
|
237
|
+
* `daemonise`: should Hutch runner process daemonise?
|
238
|
+
* `pidfile`: path to PID file the runner should use
|
239
|
+
* `channel_prefetch`: basic.qos prefetch value to use (default: `0`, no limit). See Bunny and RabbitMQ documentation.
|
240
|
+
* `publisher_confirms`: enables publisher confirms. Leaves it up to the app how they are
|
241
|
+
tracked (e.g. using `Hutch::Broker#confirm_select` callback or `Hutch::Broker#wait_for_confirms`)
|
242
|
+
* `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**.
|
243
|
+
* `log_level`: log level used by the standard Ruby logger (default: `Logger::INFO`)
|
244
|
+
* `mq_exchange`: exchange to use for publishing (default: `hutch`)
|
245
|
+
|
246
|
+
|
195
247
|
## Supported RabbitMQ Versions
|
196
248
|
|
197
249
|
Hutch requires RabbitMQ 2.x or later. 3.x releases
|
198
250
|
are recommended.
|
199
251
|
|
200
|
-
|
201
|
-
[pc-issue]: https://github.com/ruby-amqp/amqp/issues/92
|
202
|
-
[pc-gist]: https://gist.github.com/3042381
|
203
|
-
|
204
252
|
---
|
205
253
|
|
206
254
|
GoCardless ♥ open source. If you do too, come [join us](https://gocardless.com/jobs/backend_developer).
|
data/hutch.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.expand_path('../lib/hutch/version', __FILE__)
|
2
2
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
|
-
gem.add_runtime_dependency 'bunny', '>= 1.
|
4
|
+
gem.add_runtime_dependency 'bunny', '>= 1.6.1'
|
5
5
|
gem.add_runtime_dependency 'carrot-top', '~> 0.0.7'
|
6
6
|
gem.add_runtime_dependency 'multi_json', '~> 1.5'
|
7
7
|
gem.add_development_dependency 'rspec', '~> 3.0'
|
data/lib/hutch.rb
CHANGED
data/lib/hutch/broker.rb
CHANGED
@@ -88,6 +88,10 @@ module Hutch
|
|
88
88
|
logger.info 'opening rabbitmq channel'
|
89
89
|
@channel = connection.create_channel.tap do |ch|
|
90
90
|
ch.prefetch(@config[:channel_prefetch]) if @config[:channel_prefetch]
|
91
|
+
if @config[:publisher_confirms] || @config[:force_publisher_confirms]
|
92
|
+
logger.info 'enabling publisher confirms'
|
93
|
+
ch.confirm_select
|
94
|
+
end
|
91
95
|
end
|
92
96
|
end
|
93
97
|
|
@@ -188,10 +192,26 @@ module Hutch
|
|
188
192
|
properties[:message_id] ||= generate_id
|
189
193
|
|
190
194
|
logger.info("publishing message '#{message.inspect}' to #{routing_key}")
|
191
|
-
|
195
|
+
|
196
|
+
response = @exchange.publish(JSON.dump(message), {persistent: true}.
|
192
197
|
merge(properties).
|
193
198
|
merge(global_properties).
|
194
199
|
merge(non_overridable_properties))
|
200
|
+
|
201
|
+
channel.wait_for_confirms if @config[:force_publisher_confirms]
|
202
|
+
response
|
203
|
+
end
|
204
|
+
|
205
|
+
def confirm_select(*args)
|
206
|
+
@channel.confirm_select(*args)
|
207
|
+
end
|
208
|
+
|
209
|
+
def wait_for_confirms
|
210
|
+
@channel.wait_for_confirms
|
211
|
+
end
|
212
|
+
|
213
|
+
def using_publisher_confirmations?
|
214
|
+
@channel.using_publisher_confirmations?
|
195
215
|
end
|
196
216
|
|
197
217
|
private
|
data/lib/hutch/config.rb
CHANGED
@@ -31,7 +31,13 @@ module Hutch
|
|
31
31
|
namespace: nil,
|
32
32
|
daemonise: false,
|
33
33
|
pidfile: nil,
|
34
|
-
channel_prefetch: 0
|
34
|
+
channel_prefetch: 0,
|
35
|
+
# enables publisher confirms, leaves it up to the app
|
36
|
+
# how they are tracked
|
37
|
+
publisher_confirms: false,
|
38
|
+
# like `publisher_confirms` above but also
|
39
|
+
# forces waiting for a confirm for every publish
|
40
|
+
force_publisher_confirms: false
|
35
41
|
}.merge(params)
|
36
42
|
end
|
37
43
|
|
@@ -61,6 +67,10 @@ module Hutch
|
|
61
67
|
@config
|
62
68
|
end
|
63
69
|
|
70
|
+
def self.to_hash
|
71
|
+
self.user_config
|
72
|
+
end
|
73
|
+
|
64
74
|
def self.load_from_file(file)
|
65
75
|
YAML.load(file).each do |attr, value|
|
66
76
|
Hutch::Config.send("#{attr}=", value)
|
data/lib/hutch/version.rb
CHANGED
data/lib/hutch/worker.rb
CHANGED
@@ -65,7 +65,7 @@ module Hutch
|
|
65
65
|
queue = @broker.queue(consumer.get_queue_name)
|
66
66
|
@broker.bind_queue(queue, consumer.routing_keys)
|
67
67
|
|
68
|
-
queue.subscribe(
|
68
|
+
queue.subscribe(manual_ack: true) do |delivery_info, properties, payload|
|
69
69
|
handle_message(consumer, delivery_info, properties, payload)
|
70
70
|
end
|
71
71
|
end
|
data/spec/hutch/broker_spec.rb
CHANGED
@@ -92,6 +92,18 @@ describe Hutch::Broker do
|
|
92
92
|
broker.set_up_amqp_connection
|
93
93
|
end
|
94
94
|
end
|
95
|
+
|
96
|
+
context 'with force_publisher_confirms set' do
|
97
|
+
let(:force_publisher_confirms_value) { true }
|
98
|
+
before { config[:force_publisher_confirms] = force_publisher_confirms_value }
|
99
|
+
after { broker.disconnect }
|
100
|
+
|
101
|
+
it 'waits for confirmation' do
|
102
|
+
expect_any_instance_of(Bunny::Channel).
|
103
|
+
to receive(:confirm_select)
|
104
|
+
broker.set_up_amqp_connection
|
105
|
+
end
|
106
|
+
end
|
95
107
|
end
|
96
108
|
|
97
109
|
describe '#set_up_api_connection', rabbitmq: true do
|
@@ -252,6 +264,28 @@ describe Hutch::Broker do
|
|
252
264
|
end
|
253
265
|
end
|
254
266
|
end
|
267
|
+
|
268
|
+
context 'with force_publisher_confirms not set in the config' do
|
269
|
+
it 'does not wait for confirms on the channel' do
|
270
|
+
expect_any_instance_of(Bunny::Channel).
|
271
|
+
to_not receive(:wait_for_confirms)
|
272
|
+
broker.publish('test.key', 'message')
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
context 'with force_publisher_confirms set in the config' do
|
277
|
+
let(:force_publisher_confirms_value) { true }
|
278
|
+
|
279
|
+
before do
|
280
|
+
config[:force_publisher_confirms] = force_publisher_confirms_value
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'waits for confirms on the channel' do
|
284
|
+
expect_any_instance_of(Bunny::Channel).
|
285
|
+
to receive(:wait_for_confirms)
|
286
|
+
broker.publish('test.key', 'message')
|
287
|
+
end
|
288
|
+
end
|
255
289
|
end
|
256
290
|
|
257
291
|
context 'without a valid connection' do
|
data/spec/hutch/worker_spec.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hutch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Harry Marr
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bunny
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: 1.6.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: 1.6.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: carrot-top
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|