hutch 0.14.0 → 0.15.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 +4 -3
- data/CHANGELOG.md +9 -1
- data/README.md +27 -2
- data/lib/hutch/broker.rb +13 -4
- data/lib/hutch/config.rb +7 -2
- data/lib/hutch/consumer.rb +10 -0
- data/lib/hutch/version.rb +1 -1
- data/lib/hutch/worker.rb +1 -1
- data/spec/hutch/broker_spec.rb +23 -2
- data/spec/hutch/config_spec.rb +26 -0
- data/spec/hutch/consumer_spec.rb +27 -1
- data/spec/hutch/worker_spec.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4edfb298acf9e73fb226a3708e76d7e99ad345e3
|
4
|
+
data.tar.gz: d17eb84b63b21b42501570196abe6ef57ca94cde
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99ba07374f0f8bcf407ef537ea0a8342cb4368cf323c0f41deee27a37e1b6cf156dc6a72645bf2ecc6181219a0723c9c6795035d7ac3cc46ad4783f936edd516
|
7
|
+
data.tar.gz: 8a6abf7f30f6dcb3c88d968deba3115389b6a043293a75609ff5e441c94da55ac3c31d81dad4049f52710ac12bff59d4643f878ee40bac143d35b3070edf8c84
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
-
## 0.
|
1
|
+
## 0.15.0 — (unreleased)
|
2
|
+
|
3
|
+
Allow to set custom arguments per consumers by using the `arguments` setter.
|
4
|
+
Arguments are usually used by rabbitmq plugins or to set queue policies. You can
|
5
|
+
find a list of supported arguments [here](https://www.rabbitmq.com/extensions.html).
|
6
|
+
|
7
|
+
Contributed by Pierre-Louis Gottfrois.
|
8
|
+
|
9
|
+
## 0.14.0 — Feb 23rd, 2015
|
2
10
|
|
3
11
|
### Configurable Socket Timeouts
|
4
12
|
|
data/README.md
CHANGED
@@ -80,6 +80,19 @@ class FailedPaymentConsumer
|
|
80
80
|
end
|
81
81
|
```
|
82
82
|
|
83
|
+
You can also set custom arguments per consumer. This example declares a consumer with
|
84
|
+
a maximum length of 10 messages:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
class FailedPaymentConsumer
|
88
|
+
include Hutch::Consumer
|
89
|
+
consume 'gc.ps.payment.failed'
|
90
|
+
arguments 'x-max-length' => 10
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
Custom queue arguments can be found on [this page](https://www.rabbitmq.com/extensions.html).
|
95
|
+
|
83
96
|
If you are using Hutch with Rails and want to make Hutch log to the Rails
|
84
97
|
logger rather than `stdout`, add this to `config/initializers/hutch.rb`
|
85
98
|
|
@@ -134,8 +147,6 @@ mq_host: broker.yourhost.com
|
|
134
147
|
Passing a setting as a command-line option will overwrite what's specified
|
135
148
|
in the config file, allowing for easy customization.
|
136
149
|
|
137
|
-
|
138
|
-
|
139
150
|
### Loading Consumers
|
140
151
|
|
141
152
|
Using Hutch with a Rails app is simple. Either start Hutch in the working
|
@@ -153,6 +164,20 @@ $ hutch --require path/to/rails-app # loads a rails app
|
|
153
164
|
$ hutch --require path/to/file.rb # loads a ruby file
|
154
165
|
```
|
155
166
|
|
167
|
+
### Stopping Hutch
|
168
|
+
|
169
|
+
Hutch supports graceful stops. That means that if done correctly, Hutch will wait for your consumer to finish processing before exiting.
|
170
|
+
|
171
|
+
To gracefully stop your workers, you may send the following signals to your Hutch processes: `INT`, `TERM`, or `QUIT`.
|
172
|
+
|
173
|
+
```bash
|
174
|
+
kill -SIGINT 123 # or kill -2 123
|
175
|
+
kill -SIGTERM 456 # or kill -15 456
|
176
|
+
kill -SIGQUIT 789 # or kill -3 789
|
177
|
+
```
|
178
|
+
|
179
|
+
![](http://g.recordit.co/wyCdzG9Kh3.gif)
|
180
|
+
|
156
181
|
## Producers
|
157
182
|
|
158
183
|
Hutch includes a `publish` method for sending messages to Hutch consumers. When
|
data/lib/hutch/broker.rb
CHANGED
@@ -141,11 +141,11 @@ module Hutch
|
|
141
141
|
end
|
142
142
|
|
143
143
|
# Create / get a durable queue and apply namespace if it exists.
|
144
|
-
def queue(name)
|
144
|
+
def queue(name, arguments = {})
|
145
145
|
with_bunny_precondition_handler('queue') do
|
146
146
|
namespace = @config[:namespace].to_s.downcase.gsub(/[^-_:\.\w]/, "")
|
147
147
|
name = name.prepend(namespace + ":") unless namespace.empty?
|
148
|
-
channel.queue(name, durable: true)
|
148
|
+
channel.queue(name, durable: true, arguments: arguments)
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
@@ -193,7 +193,12 @@ module Hutch
|
|
193
193
|
end
|
194
194
|
|
195
195
|
def stop
|
196
|
-
|
196
|
+
# Enqueue a failing job that kills the consumer loop
|
197
|
+
channel_work_pool.shutdown
|
198
|
+
# Give `timeout` seconds to jobs that are still being processed
|
199
|
+
channel_work_pool.join(@config[:graceful_exit_timeout])
|
200
|
+
# If after `timeout` they are still running, they are killed
|
201
|
+
channel_work_pool.kill
|
197
202
|
end
|
198
203
|
|
199
204
|
def requeue(delivery_tag)
|
@@ -305,7 +310,11 @@ module Hutch
|
|
305
310
|
end
|
306
311
|
|
307
312
|
def work_pool_threads
|
308
|
-
|
313
|
+
channel_work_pool.threads || []
|
314
|
+
end
|
315
|
+
|
316
|
+
def channel_work_pool
|
317
|
+
@channel.work_pool
|
309
318
|
end
|
310
319
|
|
311
320
|
def generate_id
|
data/lib/hutch/config.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'hutch/error_handlers/logger'
|
2
|
+
require 'erb'
|
2
3
|
require 'logger'
|
3
4
|
|
4
5
|
module Hutch
|
@@ -43,7 +44,11 @@ module Hutch
|
|
43
44
|
connection_timeout: 11,
|
44
45
|
read_timeout: 11,
|
45
46
|
write_timeout: 11,
|
46
|
-
enable_http_api_use: true
|
47
|
+
enable_http_api_use: true,
|
48
|
+
# Number of seconds that a running consumer is given
|
49
|
+
# to finish its job when gracefully exiting Hutch, before
|
50
|
+
# it's killed.
|
51
|
+
graceful_exit_timeout: 11,
|
47
52
|
}.merge(params)
|
48
53
|
end
|
49
54
|
|
@@ -78,7 +83,7 @@ module Hutch
|
|
78
83
|
end
|
79
84
|
|
80
85
|
def self.load_from_file(file)
|
81
|
-
YAML.load(file).each do |attr, value|
|
86
|
+
YAML.load(ERB.new(File.read(file)).result).each do |attr, value|
|
82
87
|
Hutch::Config.send("#{attr}=", value)
|
83
88
|
end
|
84
89
|
end
|
data/lib/hutch/consumer.rb
CHANGED
@@ -32,6 +32,11 @@ module Hutch
|
|
32
32
|
@queue_name = name
|
33
33
|
end
|
34
34
|
|
35
|
+
# Allow to specify custom arguments that will be passed when creating the queue.
|
36
|
+
def arguments(arguments = {})
|
37
|
+
@arguments = arguments
|
38
|
+
end
|
39
|
+
|
35
40
|
# The RabbitMQ queue name for the consumer. This is derived from the
|
36
41
|
# fully-qualified class name. Module separators are replaced with single
|
37
42
|
# colons, camelcased class names are converted to snake case.
|
@@ -42,6 +47,11 @@ module Hutch
|
|
42
47
|
queue_name.downcase
|
43
48
|
end
|
44
49
|
|
50
|
+
# Returns consumer custom arguments.
|
51
|
+
def get_arguments
|
52
|
+
@arguments || {}
|
53
|
+
end
|
54
|
+
|
45
55
|
# Accessor for the consumer's routing key.
|
46
56
|
def routing_keys
|
47
57
|
@routing_keys ||= Set.new
|
data/lib/hutch/version.rb
CHANGED
data/lib/hutch/worker.rb
CHANGED
@@ -62,7 +62,7 @@ module Hutch
|
|
62
62
|
# Bind a consumer's routing keys to its queue, and set up a subscription to
|
63
63
|
# receive messages sent to the queue.
|
64
64
|
def setup_queue(consumer)
|
65
|
-
queue = @broker.queue(consumer.get_queue_name)
|
65
|
+
queue = @broker.queue(consumer.get_queue_name, consumer.get_arguments)
|
66
66
|
@broker.bind_queue(queue, consumer.routing_keys)
|
67
67
|
|
68
68
|
queue.subscribe(manual_ack: true) do |delivery_info, properties, payload|
|
data/spec/hutch/broker_spec.rb
CHANGED
@@ -128,14 +128,16 @@ describe Hutch::Broker do
|
|
128
128
|
|
129
129
|
describe '#queue' do
|
130
130
|
let(:channel) { double('Channel') }
|
131
|
+
let(:arguments) { { foo: :bar } }
|
131
132
|
before { allow(broker).to receive(:channel) { channel } }
|
132
133
|
|
133
134
|
it 'applies a global namespace' do
|
134
135
|
config[:namespace] = 'mirror-all.service'
|
135
136
|
expect(broker.channel).to receive(:queue) do |*args|
|
136
|
-
args.first == '
|
137
|
+
args.first == ''
|
138
|
+
args.last == arguments
|
137
139
|
end
|
138
|
-
broker.queue('test')
|
140
|
+
broker.queue('test', arguments)
|
139
141
|
end
|
140
142
|
end
|
141
143
|
|
@@ -211,6 +213,25 @@ describe Hutch::Broker do
|
|
211
213
|
end
|
212
214
|
end
|
213
215
|
|
216
|
+
describe '#stop' do
|
217
|
+
let(:thread_1) { double('Thread') }
|
218
|
+
let(:thread_2) { double('Thread') }
|
219
|
+
let(:work_pool) { double('Bunny::ConsumerWorkPool') }
|
220
|
+
let(:config) { { graceful_exit_timeout: 2 } }
|
221
|
+
|
222
|
+
before do
|
223
|
+
allow(broker).to receive(:channel_work_pool).and_return(work_pool)
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'gracefully stops the work pool' do
|
227
|
+
expect(work_pool).to receive(:shutdown)
|
228
|
+
expect(work_pool).to receive(:join).with(2)
|
229
|
+
expect(work_pool).to receive(:kill)
|
230
|
+
|
231
|
+
broker.stop
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
214
235
|
describe '#publish' do
|
215
236
|
context 'with a valid connection' do
|
216
237
|
before { broker.set_up_amqp_connection }
|
data/spec/hutch/config_spec.rb
CHANGED
@@ -97,4 +97,30 @@ describe Hutch::Config do
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
100
|
+
|
101
|
+
describe '.load_from_file' do
|
102
|
+
let(:host) { 'localhost' }
|
103
|
+
let(:username) { 'calvin' }
|
104
|
+
let(:file) do
|
105
|
+
Tempfile.new('configs.yaml').tap do |t|
|
106
|
+
t.write(config_contents)
|
107
|
+
t.rewind
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'when using ERb' do
|
112
|
+
let(:config_contents) do
|
113
|
+
<<-YAML
|
114
|
+
mq_host: 'localhost'
|
115
|
+
mq_username: '<%= "calvin" %>'
|
116
|
+
YAML
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'loads in the config data' do
|
120
|
+
Hutch::Config.load_from_file(file)
|
121
|
+
expect(Hutch::Config.mq_host).to eq host
|
122
|
+
expect(Hutch::Config.mq_username).to eq username
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
100
126
|
end
|
data/spec/hutch/consumer_spec.rb
CHANGED
@@ -22,6 +22,7 @@ describe Hutch::Consumer do
|
|
22
22
|
class ComplexConsumer
|
23
23
|
include Hutch::Consumer
|
24
24
|
consume 'hutch.test1', 'hutch.test2'
|
25
|
+
arguments foo: :bar
|
25
26
|
end
|
26
27
|
end
|
27
28
|
ComplexConsumer
|
@@ -62,11 +63,36 @@ describe Hutch::Consumer do
|
|
62
63
|
end
|
63
64
|
|
64
65
|
describe '.queue_name' do
|
66
|
+
let(:queue_name) { 'foo' }
|
67
|
+
|
65
68
|
it 'overrides the queue name' do
|
66
|
-
|
69
|
+
simple_consumer.queue_name(queue_name)
|
70
|
+
expect(simple_consumer.get_queue_name).to eq(queue_name)
|
67
71
|
end
|
68
72
|
end
|
69
73
|
|
74
|
+
describe '.arguments' do
|
75
|
+
let(:args) { { foo: :bar} }
|
76
|
+
|
77
|
+
it 'overrides the arguments' do
|
78
|
+
simple_consumer.arguments(args)
|
79
|
+
expect(simple_consumer.get_arguments).to eq(args)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '.get_arguments' do
|
85
|
+
|
86
|
+
context 'when defined' do
|
87
|
+
it { expect(complex_consumer.get_arguments).to eq(foo: :bar) }
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'when not defined' do
|
91
|
+
it { expect(simple_consumer.get_arguments).to eq({}) }
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
70
96
|
describe '.get_queue_name' do
|
71
97
|
|
72
98
|
context 'when queue name has been set explicitly' do
|
data/spec/hutch/worker_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'hutch/worker'
|
|
3
3
|
|
4
4
|
describe Hutch::Worker do
|
5
5
|
let(:consumer) { double('Consumer', routing_keys: %w( a b c ),
|
6
|
-
get_queue_name: 'consumer') }
|
6
|
+
get_queue_name: 'consumer', get_arguments: {}) }
|
7
7
|
let(:consumers) { [consumer, double('Consumer')] }
|
8
8
|
let(:broker) { Hutch::Broker.new }
|
9
9
|
subject(:worker) { Hutch::Worker.new(broker, consumers) }
|
@@ -23,7 +23,7 @@ describe Hutch::Worker do
|
|
23
23
|
before { allow(broker).to receive_messages(queue: queue, bind_queue: nil) }
|
24
24
|
|
25
25
|
it 'creates a queue' do
|
26
|
-
expect(broker).to receive(:queue).with(consumer.get_queue_name).and_return(queue)
|
26
|
+
expect(broker).to receive(:queue).with(consumer.get_queue_name, consumer.get_arguments).and_return(queue)
|
27
27
|
worker.setup_queue(consumer)
|
28
28
|
end
|
29
29
|
|
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.15.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: 2015-
|
11
|
+
date: 2015-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bunny
|