hutch 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|