hutch 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 803369cb7619eae888379612cf278d49133a3f68
4
- data.tar.gz: 4eb4a16d6b7a12441b9e56d972ebcc413b5fec82
3
+ metadata.gz: b4ae8b34c445db665d717e7c4b935ae246c793c4
4
+ data.tar.gz: d92e37a658a7a46a08500cf7c14589f7f6df2a17
5
5
  SHA512:
6
- metadata.gz: 3f557376e9db220197b6f6f99cd28621593ed3a5f0bc96e26c471fb40b7b54e3f79564cad661873b223c7688713112bbf5536b705efdb0d3aa4b86d88725cd6b
7
- data.tar.gz: d497420735d0567a167290a9de4130d66635f4ef36d5b1f674ca77e0320956518014cbc91054d72b10dc16ef3c2edc5498e47dd7a1b6ddce4edb013a757158ff
6
+ metadata.gz: 149952fbd91217d9bb7a92c7eac65607b45af0b35aaf0bba3424996376fa0f49fd205efc02b67e5b6a7f7a7a66a1dd22ad0e35ad576772905b0d91dc9da62950
7
+ data.tar.gz: 6a128089af08c252778bf0cef44cfbbc522aea4938c7a4904c9ea74e21528fc13559a3ecb5011700c36a4e87bdd9b98e171593a3e28829312d3b9162c9774d7e
@@ -1,14 +1,73 @@
1
- ## 0.10.0 — unreleased
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 `1.4.x`.
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
- - Mark your messages as persistent. This is done by passing `persistent: true`
178
- to the publish method in Ruby AMQP.
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).
@@ -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.5.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'
@@ -37,6 +37,13 @@ module Hutch
37
37
  end
38
38
  end
39
39
 
40
+ def self.disconnect
41
+ if @broker
42
+ @broker.disconnect
43
+ @connected = false
44
+ end
45
+ end
46
+
40
47
  def self.broker
41
48
  @broker
42
49
  end
@@ -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
- @exchange.publish(JSON.dump(message), {persistent: true}.
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
@@ -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)
@@ -1,4 +1,4 @@
1
1
  module Hutch
2
- VERSION = '0.10.0'.freeze
2
+ VERSION = '0.11.0'.freeze
3
3
  end
4
4
 
@@ -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(ack: true) do |delivery_info, properties, payload|
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
@@ -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
@@ -33,7 +33,7 @@ describe Hutch::Worker do
33
33
  end
34
34
 
35
35
  it 'sets up a subscription' do
36
- expect(queue).to receive(:subscribe).with(ack: true)
36
+ expect(queue).to receive(:subscribe).with(manual_ack: true)
37
37
  worker.setup_queue(consumer)
38
38
  end
39
39
  end
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.10.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-10-22 00:00:00.000000000 Z
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.5.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.5.1
26
+ version: 1.6.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: carrot-top
29
29
  requirement: !ruby/object:Gem::Requirement