hutch 0.7.0 → 0.8.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 +81 -2
- data/hutch.gemspec +1 -1
- data/lib/hutch/broker.rb +17 -12
- data/lib/hutch/config.rb +2 -1
- data/lib/hutch/consumer.rb +2 -0
- data/lib/hutch/version.rb +1 -1
- data/lib/hutch/worker.rb +2 -3
- data/spec/hutch/broker_spec.rb +14 -3
- data/spec/hutch/worker_spec.rb +5 -4
- 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: 5a5e2b2315f71a38d34043446034950e26c63612
|
4
|
+
data.tar.gz: 24f650b6681c6c7c18e5a9a067666155edae4d2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ffdefefec637a9ad46fb00207a74c78210fcc167c0dbfe6c34a91da32ec5499ea67c07f12a68af1ac0ea7e9d23a9df7b33690a9c68d9a4b765897533fcc37d18
|
7
|
+
data.tar.gz: ac34de5ef0600b31a6f3614de06508cca2c47406371a9137f43458a2533996cac906a47825c45230b5bb887633dbc15b2c859fb1bae477b77149c221e5b6f198
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,85 @@
|
|
1
|
-
## 0.
|
1
|
+
## 0.8.0 — unreleased
|
2
2
|
|
3
|
-
|
3
|
+
### Uncaught Exceptions Result in Rejected Messages
|
4
|
+
|
5
|
+
Uncaught exceptions in consumers now result in Hutch rejecting
|
6
|
+
messages (deliveries) using `basic.nack`. This way they are [dead lettered](http://www.rabbitmq.com/dlx.html).
|
7
|
+
|
8
|
+
Contributed by Garrett Johnson.
|
9
|
+
|
10
|
+
### Missing Require
|
11
|
+
|
12
|
+
`hutch/consumer.rb` no longer fails to load with the
|
13
|
+
apps that do not `require "set"`.
|
14
|
+
|
15
|
+
### Relaxed Queue Namespace Validation
|
16
|
+
|
17
|
+
Namespaces now can include any characters that are valid in RabbitMQ
|
18
|
+
queue names.
|
19
|
+
|
20
|
+
Contributed by Garrett Johnson.
|
21
|
+
|
22
|
+
### basic.qos Configuration
|
23
|
+
|
24
|
+
It is now possible to configure `basic.qos` (aka channel prefetch) setting
|
25
|
+
used by Hutch using the `:channel_prefetch` config key.
|
26
|
+
|
27
|
+
### Passwords No Longer Logged
|
28
|
+
|
29
|
+
Hutch now elides passwords from logs.
|
30
|
+
|
31
|
+
|
32
|
+
## 0.7.0 — January 14, 2014
|
33
|
+
|
34
|
+
### Optional HTTP API Use
|
35
|
+
|
36
|
+
It is now possible to make Hutch [not use RabbitMQ HTTP
|
37
|
+
API](https://github.com/gocardless/hutch/pull/69) (e.g. when the
|
38
|
+
RabbitMQ management plugin that provides it is not available).
|
39
|
+
|
40
|
+
|
41
|
+
### Extra Arguments for Hutch::Broker#publish
|
42
|
+
|
43
|
+
Extra options [passed to `Hutch::Broker#publish` will now be propagated](https://github.com/gocardless/hutch/pull/61).
|
44
|
+
|
45
|
+
|
46
|
+
### Content-Type for Messages
|
47
|
+
|
48
|
+
Messages published with Hutch now have content type set
|
49
|
+
to `application/json`.
|
50
|
+
|
51
|
+
|
52
|
+
### Greater Heartbeat Interval
|
53
|
+
|
54
|
+
Hutch now uses heartbeat interval of 30, so heartbeats won't interfere with transfers
|
55
|
+
of large messages over high latency networks (e.g. between AWS availability regions).
|
56
|
+
|
57
|
+
|
58
|
+
### Custom Queue Names
|
59
|
+
|
60
|
+
It is now possible to [specify an optional queue name](https://github.com/gocardless/hutch/pull/49):
|
61
|
+
|
62
|
+
``` ruby
|
63
|
+
class FailedPaymentConsumer
|
64
|
+
include Hutch::Consumer
|
65
|
+
consume 'gc.ps.payment.failed'
|
66
|
+
queue_name 'failed_payments'
|
67
|
+
|
68
|
+
def process(message)
|
69
|
+
mark_payment_as_failed(message[:id])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
```
|
73
|
+
|
74
|
+
### Global Properties for Publishers
|
75
|
+
|
76
|
+
[Global properties can now be specified](https://github.com/gocardless/hutch/pull/62) for publishing:
|
77
|
+
|
78
|
+
``` ruby
|
79
|
+
Hutch.global_properties = proc {
|
80
|
+
{ app_id: 'api', headers: { request_id: RequestId.request_id } }
|
81
|
+
}
|
82
|
+
```
|
4
83
|
|
5
84
|
## 0.6.0 - November 4, 2013
|
6
85
|
|
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.1.
|
4
|
+
gem.add_runtime_dependency 'bunny', '~> 1.1.2'
|
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', '~> 2.12.0'
|
data/lib/hutch/broker.rb
CHANGED
@@ -55,9 +55,8 @@ module Hutch
|
|
55
55
|
tls_key = @config[:mq_tls_cert]
|
56
56
|
tls_cert = @config[:mq_tls_key]
|
57
57
|
protocol = tls ? "amqps://" : "amqp://"
|
58
|
-
|
59
|
-
|
60
|
-
logger.info "connecting to rabbitmq (#{protocol}#{uri})"
|
58
|
+
sanitized_uri = "#{protocol}#{username}@#{host}:#{port}/#{vhost.sub(/^\//, '')}"
|
59
|
+
logger.info "connecting to rabbitmq (#{sanitized_uri})"
|
61
60
|
|
62
61
|
@connection = Bunny.new(host: host, port: port, vhost: vhost,
|
63
62
|
tls: tls, tls_key: tls_key, tls_cert: tls_cert,
|
@@ -74,14 +73,16 @@ module Hutch
|
|
74
73
|
|
75
74
|
def open_channel!
|
76
75
|
logger.info 'opening rabbitmq channel'
|
77
|
-
@channel = connection.create_channel
|
76
|
+
@channel = connection.create_channel.tap do |ch|
|
77
|
+
ch.prefetch(@config[:channel_prefetch]) if @config[:channel_prefetch]
|
78
|
+
end
|
78
79
|
end
|
79
80
|
|
80
81
|
# Set up the connection to the RabbitMQ management API. Unfortunately, this
|
81
82
|
# is necessary to do a few things that are impossible over AMQP. E.g.
|
82
83
|
# listing queues and bindings.
|
83
84
|
def set_up_api_connection
|
84
|
-
logger.info "connecting to rabbitmq
|
85
|
+
logger.info "connecting to rabbitmq HTTP API (#{api_config.sanitized_uri})"
|
85
86
|
|
86
87
|
with_authentication_error_handler do
|
87
88
|
with_connection_error_handler do
|
@@ -96,7 +97,7 @@ module Hutch
|
|
96
97
|
# Create / get a durable queue and apply namespace if it exists.
|
97
98
|
def queue(name)
|
98
99
|
with_bunny_precondition_handler('queue') do
|
99
|
-
namespace = @config[:namespace].to_s.downcase.gsub(
|
100
|
+
namespace = @config[:namespace].to_s.downcase.gsub(/[^-_:\.\w]/, "")
|
100
101
|
name = name.prepend(namespace + ":") unless namespace.empty?
|
101
102
|
channel.queue(name, durable: true)
|
102
103
|
end
|
@@ -151,6 +152,10 @@ module Hutch
|
|
151
152
|
@channel.ack(delivery_tag, false)
|
152
153
|
end
|
153
154
|
|
155
|
+
def nack(delivery_tag)
|
156
|
+
@channel.nack(delivery_tag, false, false)
|
157
|
+
end
|
158
|
+
|
154
159
|
def publish(routing_key, message, properties = {})
|
155
160
|
ensure_connection!(routing_key, message)
|
156
161
|
|
@@ -189,16 +194,16 @@ module Hutch
|
|
189
194
|
config.password = @config[:mq_password]
|
190
195
|
config.ssl = @config[:mq_api_ssl]
|
191
196
|
config.protocol = config.ssl ? "https://" : "http://"
|
192
|
-
config.
|
197
|
+
config.sanitized_uri = "#{config.protocol}#{config.username}@#{config.host}:#{config.port}/"
|
193
198
|
end
|
194
199
|
end
|
195
200
|
|
196
201
|
def with_authentication_error_handler
|
197
202
|
yield
|
198
203
|
rescue Net::HTTPServerException => ex
|
199
|
-
logger.error "
|
204
|
+
logger.error "HTTP API connection error: #{ex.message.downcase}"
|
200
205
|
if ex.response.code == '401'
|
201
|
-
raise AuthenticationError.new('invalid
|
206
|
+
raise AuthenticationError.new('invalid HTTP API credentials')
|
202
207
|
else
|
203
208
|
raise
|
204
209
|
end
|
@@ -207,15 +212,15 @@ module Hutch
|
|
207
212
|
def with_connection_error_handler
|
208
213
|
yield
|
209
214
|
rescue Errno::ECONNREFUSED => ex
|
210
|
-
logger.error "
|
211
|
-
raise ConnectionError.new("couldn't connect to
|
215
|
+
logger.error "HTTP API connection error: #{ex.message.downcase}"
|
216
|
+
raise ConnectionError.new("couldn't connect to HTTP API at #{api_config.sanitized_uri}")
|
212
217
|
end
|
213
218
|
|
214
219
|
def with_bunny_precondition_handler(item)
|
215
220
|
yield
|
216
221
|
rescue Bunny::PreconditionFailed => ex
|
217
222
|
logger.error ex.message
|
218
|
-
s = "RabbitMQ responded with Precondition Failed when creating this #{item}. " +
|
223
|
+
s = "RabbitMQ responded with 406 Precondition Failed when creating this #{item}. " +
|
219
224
|
"Perhaps it is being redeclared with non-matching attributes"
|
220
225
|
raise WorkerSetupError.new(s)
|
221
226
|
end
|
data/lib/hutch/config.rb
CHANGED
data/lib/hutch/consumer.rb
CHANGED
data/lib/hutch/version.rb
CHANGED
data/lib/hutch/worker.rb
CHANGED
@@ -85,7 +85,7 @@ module Hutch
|
|
85
85
|
broker.ack(delivery_info.delivery_tag)
|
86
86
|
rescue StandardError => ex
|
87
87
|
handle_error(properties.message_id, consumer, ex)
|
88
|
-
broker.
|
88
|
+
broker.nack(delivery_info.delivery_tag)
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
@@ -97,8 +97,7 @@ module Hutch
|
|
97
97
|
|
98
98
|
def consumers=(val)
|
99
99
|
if val.empty?
|
100
|
-
logger.warn
|
101
|
-
'no configuration issue'
|
100
|
+
logger.warn "no consumer loaded, ensure there's no configuration issue"
|
102
101
|
end
|
103
102
|
@consumers = val
|
104
103
|
end
|
data/spec/hutch/broker_spec.rb
CHANGED
@@ -58,6 +58,17 @@ describe Hutch::Broker do
|
|
58
58
|
|
59
59
|
specify { set_up_amqp_connection.should raise_error }
|
60
60
|
end
|
61
|
+
|
62
|
+
context 'with channel_prefetch set' do
|
63
|
+
let(:prefetch_value) { 1 }
|
64
|
+
before { config[:channel_prefetch] = prefetch_value }
|
65
|
+
after { broker.disconnect }
|
66
|
+
|
67
|
+
it "set's channel's prefetch" do
|
68
|
+
Bunny::Channel.any_instance.should_receive(:prefetch).with(prefetch_value)
|
69
|
+
broker.set_up_amqp_connection
|
70
|
+
end
|
71
|
+
end
|
61
72
|
end
|
62
73
|
|
63
74
|
describe '#set_up_api_connection', rabbitmq: true do
|
@@ -82,8 +93,8 @@ describe Hutch::Broker do
|
|
82
93
|
before { broker.stub(:channel) { channel } }
|
83
94
|
|
84
95
|
it 'applies a global namespace' do
|
85
|
-
config[:namespace] = 'service'
|
86
|
-
broker.channel.should_receive(:queue).with { |*args| args.first == 'service:test' }
|
96
|
+
config[:namespace] = 'mirror-all.service'
|
97
|
+
broker.channel.should_receive(:queue).with { |*args| args.first == 'mirror-all.service:test' }
|
87
98
|
broker.queue('test')
|
88
99
|
end
|
89
100
|
end
|
@@ -108,7 +119,7 @@ describe Hutch::Broker do
|
|
108
119
|
end
|
109
120
|
|
110
121
|
describe '#bind_queue' do
|
111
|
-
|
122
|
+
|
112
123
|
around { |example| broker.connect { example.run } }
|
113
124
|
|
114
125
|
let(:routing_keys) { %w( a b c ) }
|
data/spec/hutch/worker_spec.rb
CHANGED
@@ -47,6 +47,7 @@ describe Hutch::Worker do
|
|
47
47
|
let(:properties) { double('Properties', message_id: nil) }
|
48
48
|
before { consumer.stub(new: consumer_instance) }
|
49
49
|
before { broker.stub(:ack) }
|
50
|
+
before { broker.stub(:nack) }
|
50
51
|
|
51
52
|
it 'passes the message to the consumer' do
|
52
53
|
consumer_instance.should_receive(:process).
|
@@ -70,8 +71,8 @@ describe Hutch::Worker do
|
|
70
71
|
worker.handle_message(consumer, delivery_info, properties, payload)
|
71
72
|
end
|
72
73
|
|
73
|
-
it '
|
74
|
-
broker.should_receive(:
|
74
|
+
it 'rejects the message' do
|
75
|
+
broker.should_receive(:nack).with(delivery_info.delivery_tag)
|
75
76
|
worker.handle_message(consumer, delivery_info, properties, payload)
|
76
77
|
end
|
77
78
|
end
|
@@ -86,8 +87,8 @@ describe Hutch::Worker do
|
|
86
87
|
worker.handle_message(consumer, delivery_info, properties, payload)
|
87
88
|
end
|
88
89
|
|
89
|
-
it '
|
90
|
-
broker.should_receive(:
|
90
|
+
it 'rejects the message' do
|
91
|
+
broker.should_receive(:nack).with(delivery_info.delivery_tag)
|
91
92
|
worker.handle_message(consumer, delivery_info, properties, payload)
|
92
93
|
end
|
93
94
|
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.
|
4
|
+
version: 0.8.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-02-13 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.1.
|
19
|
+
version: 1.1.2
|
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.1.
|
26
|
+
version: 1.1.2
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: carrot-top
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|