hutch 0.27.0 → 0.28.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -5
- data/CHANGELOG.md +28 -1
- data/Gemfile +1 -1
- data/README.md +40 -0
- data/bin/ci/before_build.sh +20 -0
- data/bin/ci/install_on_debian.sh +2 -2
- data/hutch.gemspec +2 -2
- data/lib/hutch/broker.rb +9 -6
- data/lib/hutch/cli.rb +14 -10
- data/lib/hutch/consumer.rb +24 -1
- data/lib/hutch/publisher.rb +1 -1
- data/lib/hutch/version.rb +1 -1
- data/spec/hutch/consumer_spec.rb +68 -2
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 587ca7c6e7515a0efcf8999a5ad3bfc1ef186a701a758260f68abb528641b7cd
|
4
|
+
data.tar.gz: 7f4353919efb856a7ef9af3dc71e7d2024aaa85c1183da3a191bbbf2c22a8492
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c00226f20383fc7ec3503197783a48e0d8f153dd7e45ea7d89dda7631f2e527f71b6d15182be677d24818e1ce1cfcf6766765ad6a0e67b753b76cc145b46782
|
7
|
+
data.tar.gz: 530af1729a20c10d555bac21529d18c94cb07b1957ce2b6c5386adede9e400c7f7f400491c7c716378fd4fc8d8a955d2537e956dc6d6994aab5fc3cd2f2b5970
|
data/.travis.yml
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
dist: bionic
|
2
|
+
sudo: required
|
3
|
+
|
1
4
|
language: ruby
|
2
5
|
cache: bundler
|
3
6
|
before_install:
|
@@ -5,18 +8,16 @@ before_install:
|
|
5
8
|
before_script:
|
6
9
|
- "./bin/ci/install_on_debian.sh"
|
7
10
|
- until sudo lsof -i:5672; do echo "Waiting for RabbitMQ to start..."; sleep 1; done
|
11
|
+
- "./bin/ci/before_build.sh"
|
8
12
|
matrix:
|
9
13
|
include:
|
10
14
|
- rvm: "2.6.4"
|
11
15
|
- rvm: "2.5.6"
|
12
16
|
- rvm: "2.4.7"
|
13
17
|
- rvm: "2.3.8"
|
14
|
-
- rvm: "jruby-9.2.
|
18
|
+
- rvm: "jruby-9.2.9.0"
|
15
19
|
- rvm: "ruby-head"
|
16
20
|
allow_failures:
|
17
21
|
rvm:
|
18
|
-
- "jruby-9.2.
|
22
|
+
- "jruby-9.2.9.0"
|
19
23
|
- ruby-head
|
20
|
-
|
21
|
-
services:
|
22
|
-
- rabbitmq
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,34 @@
|
|
1
1
|
## 0.28.0 (under development)
|
2
2
|
|
3
|
-
|
3
|
+
### Enhancements
|
4
|
+
|
5
|
+
* Add lazy and quorum options for queues.
|
6
|
+
|
7
|
+
GitHub issue: [gocardless/hutch#341](https://github.com/gocardless/hutch/pull/341)
|
8
|
+
|
9
|
+
Contributed by: Arthur Del Esposte
|
10
|
+
|
11
|
+
* Log level in the message publisher switched to DEBUG.
|
12
|
+
|
13
|
+
GitHub issue: [gocardless/hutch#343](https://github.com/gocardless/hutch/pull/343)
|
14
|
+
|
15
|
+
Contributed by: Codruț Constantin Gușoi
|
16
|
+
|
17
|
+
### Documentation
|
18
|
+
|
19
|
+
* Add zeitwerk note to README.
|
20
|
+
|
21
|
+
GitHub issue: [gocardless/hutch#342](https://github.com/gocardless/hutch/pull/342)
|
22
|
+
|
23
|
+
Contributed by: Paolo Zaccagnini
|
24
|
+
|
25
|
+
### CI
|
26
|
+
|
27
|
+
* Use jruby-9.2.9.0
|
28
|
+
|
29
|
+
GitHub issue: [gocardless/hutch#336](https://github.com/gocardless/hutch/pull/336)
|
4
30
|
|
31
|
+
Contributed by: Olle Jonsson
|
5
32
|
|
6
33
|
## 0.27.0 (September 9th, 2019)
|
7
34
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -109,6 +109,28 @@ class FailedPaymentConsumer
|
|
109
109
|
end
|
110
110
|
```
|
111
111
|
|
112
|
+
It is possible to set some custom options to consumer's queue explicitly.
|
113
|
+
This example sets the consumer's queue as a
|
114
|
+
[quorum queue](https://www.rabbitmq.com/quorum-queues.html)
|
115
|
+
and to operate in the [lazy mode](https://www.rabbitmq.com/lazy-queues.html).
|
116
|
+
The `initial_group_size`
|
117
|
+
[argument](https://www.rabbitmq.com/quorum-queues.html#replication-factor) is
|
118
|
+
optional.
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
class FailedPaymentConsumer
|
122
|
+
include Hutch::Consumer
|
123
|
+
consume 'gc.ps.payment.failed'
|
124
|
+
queue_name 'failed_payments'
|
125
|
+
lazy_queue
|
126
|
+
quorum_queue initial_group_size: 3
|
127
|
+
|
128
|
+
def process(message)
|
129
|
+
mark_payment_as_failed(message[:id])
|
130
|
+
end
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
112
134
|
You can also set custom arguments per consumer. This example declares a consumer with
|
113
135
|
a maximum length of 10 messages:
|
114
136
|
|
@@ -219,6 +241,24 @@ directory of a Rails app, or pass the path to a Rails app in with the
|
|
219
241
|
the `app/consumers/` directory, to allow them to be auto-loaded when Rails
|
220
242
|
boots.
|
221
243
|
|
244
|
+
If you're using the new Zeitwerk autoloader (enabled by default in Rails 6)
|
245
|
+
and the consumers are not loaded in development environment you will need to
|
246
|
+
trigger the autoloading in an initializer with
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
::Zeitwerk::Loader.eager_load_all
|
250
|
+
```
|
251
|
+
|
252
|
+
or with something more specific like
|
253
|
+
|
254
|
+
```ruby
|
255
|
+
autoloader = Rails.autoloaders.main
|
256
|
+
|
257
|
+
Dir.glob(File.join('app/consumers', '*_consumer.rb')).each do |consumer|
|
258
|
+
autoloader.preload(consumer)
|
259
|
+
end
|
260
|
+
```
|
261
|
+
|
222
262
|
To require files that define consumers manually, simply pass each file as an
|
223
263
|
option to `--require`. Hutch will automatically detect whether you've provided
|
224
264
|
a Rails app or a standard file, and take the appropriate behaviour:
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env sh
|
2
|
+
|
3
|
+
CTL=${BUNNY_RABBITMQCTL:-"sudo rabbitmqctl"}
|
4
|
+
PLUGINS=${BUNNY_RABBITMQ_PLUGINS:-"sudo rabbitmq-plugins"}
|
5
|
+
|
6
|
+
echo "Will use rabbitmqctl at ${CTL}"
|
7
|
+
echo "Will use rabbitmq-plugins at ${PLUGINS}"
|
8
|
+
|
9
|
+
$PLUGINS enable rabbitmq_management
|
10
|
+
|
11
|
+
sleep 3
|
12
|
+
|
13
|
+
# guest:guest has full access to /
|
14
|
+
$CTL add_vhost /
|
15
|
+
$CTL add_user guest guest
|
16
|
+
$CTL set_permissions -p / guest ".*" ".*" ".*"
|
17
|
+
|
18
|
+
# Reduce retention policy for faster publishing of stats
|
19
|
+
$CTL eval 'supervisor2:terminate_child(rabbit_mgmt_sup_sup, rabbit_mgmt_sup), application:set_env(rabbitmq_management, sample_retention_policies, [{global, [{605, 1}]}, {basic, [{605, 1}]}, {detailed, [{10, 1}]}]), rabbit_mgmt_sup_sup:start_child().' || true
|
20
|
+
$CTL eval 'supervisor2:terminate_child(rabbit_mgmt_agent_sup_sup, rabbit_mgmt_agent_sup), application:set_env(rabbitmq_management_agent, sample_retention_policies, [{global, [{605, 1}]}, {basic, [{605, 1}]}, {detailed, [{10, 1}]}]), rabbit_mgmt_agent_sup_sup:start_child().' || true
|
data/bin/ci/install_on_debian.sh
CHANGED
@@ -4,8 +4,8 @@ sudo apt-get install -y wget
|
|
4
4
|
wget -O - "https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc" | sudo apt-key add -
|
5
5
|
|
6
6
|
sudo tee /etc/apt/sources.list.d/bintray.rabbitmq.list <<EOF
|
7
|
-
deb https://dl.bintray.com/rabbitmq-erlang/debian
|
8
|
-
deb https://dl.bintray.com/rabbitmq/debian
|
7
|
+
deb https://dl.bintray.com/rabbitmq-erlang/debian bionic erlang
|
8
|
+
deb https://dl.bintray.com/rabbitmq/debian bionic main
|
9
9
|
EOF
|
10
10
|
|
11
11
|
sudo apt-get update -y
|
data/hutch.gemspec
CHANGED
@@ -6,10 +6,10 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.add_runtime_dependency 'march_hare', '>= 3.0.0'
|
7
7
|
else
|
8
8
|
gem.platform = Gem::Platform::RUBY
|
9
|
-
gem.add_runtime_dependency 'bunny', '>= 2.
|
9
|
+
gem.add_runtime_dependency 'bunny', '>= 2.14', '< 2.16'
|
10
10
|
end
|
11
11
|
gem.add_runtime_dependency 'carrot-top', '~> 0.0.7'
|
12
|
-
gem.add_runtime_dependency 'multi_json', '~> 1.
|
12
|
+
gem.add_runtime_dependency 'multi_json', '~> 1.14'
|
13
13
|
gem.add_runtime_dependency 'activesupport', '>= 4.2', '< 7'
|
14
14
|
|
15
15
|
gem.name = 'hutch'
|
data/lib/hutch/broker.rb
CHANGED
@@ -181,12 +181,15 @@ module Hutch
|
|
181
181
|
# Return a mapping of queue names to the routing keys they're bound to.
|
182
182
|
def bindings
|
183
183
|
results = Hash.new { |hash, key| hash[key] = [] }
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
184
|
+
|
185
|
+
filtered = api_client.bindings.
|
186
|
+
reject { |b| b['destination'] == b['routing_key'] }.
|
187
|
+
select { |b| b['source'] == @config[:mq_exchange] && b['vhost'] == @config[:mq_vhost] }
|
188
|
+
|
189
|
+
filtered.each do |binding|
|
188
190
|
results[binding['destination']] << binding['routing_key']
|
189
191
|
end
|
192
|
+
|
190
193
|
results
|
191
194
|
end
|
192
195
|
|
@@ -194,8 +197,8 @@ module Hutch
|
|
194
197
|
def unbind_redundant_bindings(queue, routing_keys)
|
195
198
|
return unless http_api_use_enabled?
|
196
199
|
|
197
|
-
bindings.
|
198
|
-
|
200
|
+
filtered = bindings.select { |dest, keys| dest == queue.name }
|
201
|
+
filtered.each do |dest, keys|
|
199
202
|
keys.reject { |key| routing_keys.include?(key) }.each do |key|
|
200
203
|
logger.debug "removing redundant binding #{queue.name} <--> #{key}"
|
201
204
|
queue.unbind(exchange, routing_key: key)
|
data/lib/hutch/cli.rb
CHANGED
@@ -33,6 +33,20 @@ module Hutch
|
|
33
33
|
def load_app
|
34
34
|
# Try to load a Rails app in the current directory
|
35
35
|
load_rails_app('.') if Hutch::Config.autoload_rails
|
36
|
+
set_up_code_paths!
|
37
|
+
|
38
|
+
# Because of the order things are required when we run the Hutch binary
|
39
|
+
# in hutch/bin, the Sentry Raven gem gets required **after** the error
|
40
|
+
# handlers are set up. Due to this, we never got any Sentry notifications
|
41
|
+
# when an error occurred in any of the consumers.
|
42
|
+
if defined?(Raven)
|
43
|
+
Hutch::Config[:error_handlers] << Hutch::ErrorHandlers::Sentry.new
|
44
|
+
end
|
45
|
+
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def set_up_code_paths!
|
36
50
|
Hutch::Config.require_paths.each do |path|
|
37
51
|
# See if each path is a Rails app. If so, try to load it.
|
38
52
|
next if load_rails_app(path)
|
@@ -51,16 +65,6 @@ module Hutch
|
|
51
65
|
$LOAD_PATH.pop
|
52
66
|
end
|
53
67
|
end
|
54
|
-
|
55
|
-
# Because of the order things are required when we run the Hutch binary
|
56
|
-
# in hutch/bin, the Sentry Raven gem gets required **after** the error
|
57
|
-
# handlers are set up. Due to this, we never got any Sentry notifications
|
58
|
-
# when an error occurred in any of the consumers.
|
59
|
-
if defined?(Raven)
|
60
|
-
Hutch::Config[:error_handlers] << Hutch::ErrorHandlers::Sentry.new
|
61
|
-
end
|
62
|
-
|
63
|
-
true
|
64
68
|
end
|
65
69
|
|
66
70
|
def load_rails_app(path)
|
data/lib/hutch/consumer.rb
CHANGED
@@ -29,13 +29,30 @@ module Hutch
|
|
29
29
|
# wants to subscribe to.
|
30
30
|
def consume(*routing_keys)
|
31
31
|
@routing_keys = self.routing_keys.union(routing_keys)
|
32
|
+
@queue_mode = 'default'
|
33
|
+
@queue_type = 'classic'
|
32
34
|
end
|
33
35
|
|
36
|
+
attr_reader :queue_mode, :queue_type, :initial_group_size
|
37
|
+
|
34
38
|
# Explicitly set the queue name
|
35
39
|
def queue_name(name)
|
36
40
|
@queue_name = name
|
37
41
|
end
|
38
42
|
|
43
|
+
# Explicitly set the queue mode to 'lazy'
|
44
|
+
def lazy_queue
|
45
|
+
@queue_mode = 'lazy'
|
46
|
+
end
|
47
|
+
|
48
|
+
# Explicitly set the queue type to 'quorum'
|
49
|
+
# @param [Hash] options the options params related to quorum queue
|
50
|
+
# @option options [Integer] :initial_group_size Initial Replication Factor
|
51
|
+
def quorum_queue(options = {})
|
52
|
+
@queue_type = 'quorum'
|
53
|
+
@initial_group_size = options[:initial_group_size]
|
54
|
+
end
|
55
|
+
|
39
56
|
# Allow to specify custom arguments that will be passed when creating the queue.
|
40
57
|
def arguments(arguments = {})
|
41
58
|
@arguments = arguments
|
@@ -58,7 +75,13 @@ module Hutch
|
|
58
75
|
|
59
76
|
# Returns consumer custom arguments.
|
60
77
|
def get_arguments
|
61
|
-
@arguments || {}
|
78
|
+
all_arguments = @arguments || {}
|
79
|
+
all_arguments['x-queue-mode'] = @queue_mode
|
80
|
+
all_arguments['x-queue-type'] = @queue_type
|
81
|
+
if @initial_group_size
|
82
|
+
all_arguments['x-quorum-initial-group-size'] = @initial_group_size
|
83
|
+
end
|
84
|
+
all_arguments
|
62
85
|
end
|
63
86
|
|
64
87
|
# Accessor for the consumer's routing key.
|
data/lib/hutch/publisher.rb
CHANGED
data/lib/hutch/version.rb
CHANGED
data/spec/hutch/consumer_spec.rb
CHANGED
@@ -28,6 +28,19 @@ describe Hutch::Consumer do
|
|
28
28
|
ComplexConsumer
|
29
29
|
end
|
30
30
|
|
31
|
+
let(:consumer_with_custom_queue_options) do
|
32
|
+
unless defined? ConsumerWithCustomQueueOptions
|
33
|
+
class ConsumerWithCustomQueueOptions
|
34
|
+
include Hutch::Consumer
|
35
|
+
consume 'hutch.test1'
|
36
|
+
arguments foo: :bar
|
37
|
+
lazy_queue
|
38
|
+
quorum_queue
|
39
|
+
end
|
40
|
+
end
|
41
|
+
ConsumerWithCustomQueueOptions
|
42
|
+
end
|
43
|
+
|
31
44
|
describe 'module inclusion' do
|
32
45
|
it 'registers the class as a consumer' do
|
33
46
|
expect(Hutch).to receive(:register_consumer) do |klass|
|
@@ -71,6 +84,36 @@ describe Hutch::Consumer do
|
|
71
84
|
end
|
72
85
|
end
|
73
86
|
|
87
|
+
describe '.lazy_queue' do
|
88
|
+
it 'does not use lazy mode by default' do
|
89
|
+
expect(simple_consumer.queue_mode).to eq('default')
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when queue mode has been set explicitly to lazy' do
|
93
|
+
it 'sets queue mode to lazy' do
|
94
|
+
expect(consumer_with_custom_queue_options.queue_mode).to eq('lazy')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '.quorum_queue' do
|
100
|
+
it 'does not have quorum type by default' do
|
101
|
+
expect(simple_consumer.queue_type).to eq('classic')
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'when queue type has been set explicitly to quorum' do
|
105
|
+
it 'sets queue type to quorum' do
|
106
|
+
expect(consumer_with_custom_queue_options.queue_type).to eq('quorum')
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'accepts initial group size as an option' do
|
110
|
+
consumer = simple_consumer
|
111
|
+
expect { consumer.quorum_queue(initial_group_size: 3) }
|
112
|
+
.to change { consumer.initial_group_size }.to(3)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
74
117
|
describe '.arguments' do
|
75
118
|
let(:args) { { foo: :bar} }
|
76
119
|
|
@@ -84,13 +127,36 @@ describe Hutch::Consumer do
|
|
84
127
|
describe '.get_arguments' do
|
85
128
|
|
86
129
|
context 'when defined' do
|
87
|
-
it { expect(complex_consumer.get_arguments).to
|
130
|
+
it { expect(complex_consumer.get_arguments).to include(foo: :bar) }
|
88
131
|
end
|
89
132
|
|
90
133
|
context 'when not defined' do
|
91
|
-
it
|
134
|
+
it 'has the default values for queue custom options' do
|
135
|
+
expect(simple_consumer.get_arguments).to have_key('x-queue-mode')
|
136
|
+
.and have_key('x-queue-type')
|
137
|
+
end
|
92
138
|
end
|
93
139
|
|
140
|
+
context 'when queue is lazy' do
|
141
|
+
it 'has the x-queue-mode argument set to lazy' do
|
142
|
+
expect(consumer_with_custom_queue_options.get_arguments['x-queue-mode'])
|
143
|
+
.to eq('lazy')
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context "when queue's type is quorum" do
|
148
|
+
let(:arguments) { consumer_with_custom_queue_options.get_arguments }
|
149
|
+
it 'has the x-queue-type argument set to quorum' do
|
150
|
+
expect(arguments['x-queue-type']).to eq('quorum')
|
151
|
+
expect(arguments).to_not have_key('x-quorum-initial-group-size')
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'has the x-quorum-initial-group-size argument set to quorum' do
|
155
|
+
consumer_with_custom_queue_options.quorum_queue(initial_group_size: 5)
|
156
|
+
expect(arguments['x-queue-type']).to eq('quorum')
|
157
|
+
expect(arguments['x-quorum-initial-group-size']).to eq(5)
|
158
|
+
end
|
159
|
+
end
|
94
160
|
end
|
95
161
|
|
96
162
|
describe '.get_queue_name' do
|
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.28.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:
|
11
|
+
date: 2020-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bunny
|
@@ -16,20 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '2.
|
19
|
+
version: '2.14'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '2.
|
22
|
+
version: '2.16'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '2.
|
29
|
+
version: '2.14'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '2.
|
32
|
+
version: '2.16'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: carrot-top
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,14 +50,14 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '1.
|
53
|
+
version: '1.14'
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: '1.
|
60
|
+
version: '1.14'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: activesupport
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- LICENSE
|
98
98
|
- README.md
|
99
99
|
- Rakefile
|
100
|
+
- bin/ci/before_build.sh
|
100
101
|
- bin/ci/install_on_debian.sh
|
101
102
|
- bin/hutch
|
102
103
|
- examples/consumer.rb
|