hutch 0.19.0-java → 0.20.0-java

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3780a985cc41fd9bb1d5f1a9bf09c66ff5eeacc8
4
- data.tar.gz: 2c39b6799d48cfcc22e9ba30d02adb5c0ffe3347
3
+ metadata.gz: c1038e31f77b098d63251aa624b6035949cfbc65
4
+ data.tar.gz: 43f9f3c5b968a17ecf8820962517ef2bb80e3334
5
5
  SHA512:
6
- metadata.gz: eedfd7d489f9eed88c3dccb2b4c2e68923addd22e694cfccb6d0af5051fd965b288f5075dded20f487e209a93072e4f1ec15cd44e85f1c3313800e299ec0d88d
7
- data.tar.gz: 00b14523051465133e369643ebe4d4f0e2d028532afca8650143fe3a63b46ef0862960235cd4191816d609ef104f458a4a09229c805c9ba3aa96cd03d3b2e5ff
6
+ metadata.gz: 90b98b306b7d9fda474f167e7add3053d5f10a2f86aa462fc681cfb1a7d17a77a5fc986c51e05ad57e2c754a8da2ca44067e8b6a055a9364cb86e6da11b7cb53
7
+ data.tar.gz: 6ae1a0603097859cd14df46acea9a2352951ef9cab8ab0c06ca88113e43158ce694c31b3a12855d1ce8613815f9b775f5d40fd503fb0d3fd57e8f30803a1cde5
data/CHANGELOG.md CHANGED
@@ -1,4 +1,68 @@
1
- ## 0.19.0 — (unreleased)
1
+ ## 0.20.0 — (unreleased)
2
+
3
+ ### Hutch::Exception includes Bunny::Exception
4
+
5
+ `Hutch::Exception` now inherits from `Bunny::Exception` which
6
+ inherits from `StandardError`.
7
+
8
+ GH issue: [#137](https://github.com/gocardless/hutch/issues/137).
9
+
10
+
11
+ ### Pluggable (Negative) Acknowledge Handlers
12
+
13
+ Hutch now can be configured to use a user-provided
14
+ object(s) to perform acknowledgement on consumer exceptions.
15
+
16
+ For example, this is what the default handler looks like:
17
+
18
+ ``` ruby
19
+ require 'hutch/logging'
20
+ require 'hutch/acknowledgements/base'
21
+
22
+ module Hutch
23
+ module Acknowledgements
24
+ class NackOnAllFailures < Base
25
+ include Logging
26
+
27
+ def handle(delivery_info, properties, broker, ex)
28
+ prefix = "message(#{properties.message_id || '-'}): "
29
+ logger.debug "#{prefix} nacking message"
30
+
31
+ broker.nack(delivery_info.delivery_tag)
32
+
33
+ # terminates further chain processing
34
+ true
35
+ end
36
+ end
37
+ end
38
+ end
39
+ ```
40
+
41
+ Handlers are configured similarly to exception notification handlers,
42
+ via `:error_acknowledgements` in Hutch config.
43
+
44
+ Contributed by Derek Kastner.
45
+
46
+ GH issue: [#177](https://github.com/gocardless/hutch/pull/177).
47
+
48
+
49
+ ### Configurable Exchange Properties
50
+
51
+ `:mq_exchange_options` is a new config option that can be used
52
+ to provide a hash of exchange attributes (durable, auto-delete).
53
+ The options will be passed directly to Bunny.
54
+
55
+ Contributed by Derek Kastner.
56
+
57
+ GH issue: [#170](https://github.com/gocardless/hutch/pull/170).
58
+
59
+
60
+ ### Bunny Update
61
+
62
+ Bunny is updated to 2.2.1.
63
+
64
+
65
+ ## 0.19.0 — September 7th, 2015
2
66
 
3
67
  ### Pluggable Serialisers
4
68
 
data/README.md CHANGED
@@ -20,6 +20,11 @@ Hutch is a moderately mature project (started in early 2013)
20
20
  that was extracted from production systems.
21
21
 
22
22
 
23
+ ## Supported Ruby Versions
24
+
25
+ Hutch requires CRuby 2.0+ or JRuby 9K.
26
+
27
+
23
28
  ## Overview
24
29
 
25
30
  Hutch is a conventions-based framework for writing services that communicate
@@ -31,7 +36,8 @@ With Hutch, consumers are stored in separate files and include the `Hutch::Consu
31
36
  They are then loaded by a command line runner which connects to RabbitMQ, sets up queues and bindings,
32
37
  and so on. Publishers connect to RabbitMQ via `Hutch.connect` and publish using `Hutch.publish`.
33
38
 
34
- Hutch uses [Bunny](http://rubybunny.info) under the hood.
39
+ Hutch uses [Bunny](http://rubybunny.info) or [March Hare](http://rubymarchhare.info)
40
+ (on JRuby) under the hood.
35
41
 
36
42
 
37
43
  ## Defining Consumers
@@ -300,6 +306,10 @@ Known configuration parameters are:
300
306
  tracked (e.g. using `Hutch::Broker#confirm_select` callback or `Hutch::Broker#wait_for_confirms`)
301
307
  * `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**.
302
308
  * `log_level`: log level used by the standard Ruby logger (default: `Logger::INFO`)
309
+ * `error_handlers`: a list of error handler objects, see classes in `Hutch::ErrorHandlers`. All configured
310
+ handlers will be invoked unconditionally in the order listed.
311
+ * `error_acknowledgements`: a chain of responsibility of objects that acknowledge/reject/requeue messages when an
312
+ exception happens, see classes in `Hutch::Acknowledgements`.
303
313
  * `mq_exchange`: exchange to use for publishing (default: `hutch`)
304
314
  * `heartbeat`: [RabbitMQ heartbeat timeout](http://rabbitmq.com/heartbeats.html) (default: `30`)
305
315
  * `connection_timeout`: Bunny's socket open timeout (default: `11`)
data/hutch.gemspec CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
6
6
  gem.add_runtime_dependency 'march_hare', '>= 2.11.0'
7
7
  else
8
8
  gem.platform = Gem::Platform::RUBY
9
- gem.add_runtime_dependency 'bunny', '>= 2.2.0'
9
+ gem.add_runtime_dependency 'bunny', '>= 2.2.1'
10
10
  end
11
11
  gem.add_runtime_dependency 'carrot-top', '~> 0.0.7'
12
12
  gem.add_runtime_dependency 'multi_json', '~> 1.11.2'
@@ -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
data/lib/hutch/broker.rb CHANGED
@@ -52,10 +52,11 @@ module Hutch
52
52
  open_channel!
53
53
 
54
54
  exchange_name = @config[:mq_exchange]
55
+ exchange_options = { durable: true }.merge @config[:mq_exchange_options]
55
56
  logger.info "using topic exchange '#{exchange_name}'"
56
57
 
57
58
  with_bunny_precondition_handler('exchange') do
58
- @exchange = @channel.topic(exchange_name, durable: true)
59
+ @exchange = @channel.topic(exchange_name, exchange_options)
59
60
  end
60
61
  end
61
62
 
data/lib/hutch/config.rb CHANGED
@@ -8,11 +8,12 @@ module Hutch
8
8
  module Config
9
9
  require 'yaml'
10
10
 
11
- def self.initialize(params={})
11
+ def self.initialize(params = {})
12
12
  @config = {
13
13
  mq_host: 'localhost',
14
14
  mq_port: 5672,
15
15
  mq_exchange: 'hutch', # TODO: should this be required?
16
+ mq_exchange_options: {},
16
17
  mq_vhost: '/',
17
18
  mq_tls: false,
18
19
  mq_tls_cert: nil,
@@ -32,6 +33,9 @@ module Hutch
32
33
  require_paths: [],
33
34
  autoload_rails: true,
34
35
  error_handlers: [Hutch::ErrorHandlers::Logger.new],
36
+ # note that this is not a list, it is a chain of responsibility
37
+ # that will fall back to "nack unconditionally"
38
+ error_acknowledgements: [],
35
39
  tracer: Hutch::Tracers::NullTracer,
36
40
  namespace: nil,
37
41
  daemonise: false,
@@ -1,5 +1,8 @@
1
+ require "bunny/exceptions"
2
+
1
3
  module Hutch
2
- class Exception < StandardError; end
4
+ # Bunny::Exception inherits from StandardError
5
+ class Exception < Bunny::Exception; end
3
6
  class ConnectionError < Exception; end
4
7
  class AuthenticationError < Exception; end
5
8
  class WorkerSetupError < Exception; end
data/lib/hutch/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Hutch
2
- VERSION = '0.19.0'.freeze
2
+ VERSION = '0.20.0'.freeze
3
3
  end
4
4
 
data/lib/hutch/worker.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'hutch/message'
2
2
  require 'hutch/logging'
3
3
  require 'hutch/broker'
4
+ require 'hutch/acknowledgements/nack_on_all_failures'
4
5
  require 'carrot-top'
5
6
 
6
7
  module Hutch
@@ -118,7 +119,7 @@ module Hutch
118
119
  with_tracing(consumer_instance).handle(message)
119
120
  broker.ack(delivery_info.delivery_tag)
120
121
  rescue StandardError => ex
121
- broker.nack(delivery_info.delivery_tag)
122
+ acknowledge_error(delivery_info, properties, broker, ex)
122
123
  handle_error(properties.message_id, payload, consumer, ex)
123
124
  end
124
125
  end
@@ -133,11 +134,23 @@ module Hutch
133
134
  end
134
135
  end
135
136
 
137
+ def acknowledge_error(delivery_info, properties, broker, ex)
138
+ acks = error_acknowledgements +
139
+ [Hutch::Acknowledgements::NackOnAllFailures.new]
140
+ acks.find do |backend|
141
+ backend.handle(delivery_info, properties, broker, ex)
142
+ end
143
+ end
144
+
136
145
  def consumers=(val)
137
146
  if val.empty?
138
147
  logger.warn "no consumer loaded, ensure there's no configuration issue"
139
148
  end
140
149
  @consumers = val
141
150
  end
151
+
152
+ def error_acknowledgements
153
+ Hutch::Config[:error_acknowledgements]
154
+ end
142
155
  end
143
156
  end
@@ -63,6 +63,25 @@ describe Hutch::Worker do
63
63
  worker.handle_message(consumer, delivery_info, properties, payload)
64
64
  end
65
65
 
66
+ context 'when the consumer fails and a requeue is configured' do
67
+
68
+ it 'requeues the message' do
69
+ allow(consumer_instance).to receive(:process).and_raise('failed')
70
+ requeuer = double
71
+ allow(requeuer).to receive(:handle).ordered { |delivery_info, properties, broker, e|
72
+ broker.requeue delivery_info.delivery_tag
73
+ true
74
+ }
75
+ allow(worker).to receive(:error_acknowledgements).and_return([requeuer])
76
+ expect(broker).to_not receive(:ack)
77
+ expect(broker).to_not receive(:nack)
78
+ expect(broker).to receive(:requeue)
79
+
80
+ worker.handle_message(consumer, delivery_info, properties, payload)
81
+ end
82
+ end
83
+
84
+
66
85
  context 'when the consumer raises an exception' do
67
86
  before { allow(consumer_instance).to receive(:process).and_raise('a consumer error') }
68
87
 
@@ -95,5 +114,40 @@ describe Hutch::Worker do
95
114
  end
96
115
  end
97
116
  end
117
+
118
+
119
+ describe '#acknowledge_error' do
120
+ let(:delivery_info) { double('Delivery Info', routing_key: '',
121
+ delivery_tag: 'dt') }
122
+ let(:properties) { double('Properties', message_id: 'abc123') }
123
+
124
+ subject { worker.acknowledge_error delivery_info, properties, broker, StandardError.new }
125
+
126
+ it 'stops when it runs a successful acknowledgement' do
127
+ skip_ack = double handle: false
128
+ always_ack = double handle: true
129
+ never_used = double handle: true
130
+
131
+ allow(worker).
132
+ to receive(:error_acknowledgements).
133
+ and_return([skip_ack, always_ack, never_used])
134
+
135
+ expect(never_used).to_not receive(:handle)
136
+
137
+ subject
138
+ end
139
+
140
+ it 'defaults to nacking' do
141
+ skip_ack = double handle: false
142
+
143
+ allow(worker).
144
+ to receive(:error_acknowledgements).
145
+ and_return([skip_ack, skip_ack])
146
+
147
+ expect(broker).to receive(:nack)
148
+
149
+ subject
150
+ end
151
+ end
98
152
  end
99
153
 
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.19.0
4
+ version: 0.20.0
5
5
  platform: java
6
6
  authors:
7
7
  - Harry Marr
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-17 00:00:00.000000000 Z
11
+ date: 2015-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -116,6 +116,8 @@ files:
116
116
  - examples/producer.rb
117
117
  - hutch.gemspec
118
118
  - lib/hutch.rb
119
+ - lib/hutch/acknowledgements/base.rb
120
+ - lib/hutch/acknowledgements/nack_on_all_failures.rb
119
121
  - lib/hutch/adapter.rb
120
122
  - lib/hutch/adapters/bunny.rb
121
123
  - lib/hutch/adapters/march_hare.rb