hutch 0.27.0 → 0.28.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/.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
|