hutch 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: db5d3539145e0b5196542b4157d4262045f4e414
4
- data.tar.gz: 072daf962f5ff1cd2c63278b97bd2d11efcd37e0
3
+ metadata.gz: 803369cb7619eae888379612cf278d49133a3f68
4
+ data.tar.gz: 4eb4a16d6b7a12441b9e56d972ebcc413b5fec82
5
5
  SHA512:
6
- metadata.gz: fd18ffdbf03f1bbc8f18e9bbb71a3e92937392873c482ed1a2ba2bf7ccb6fc1b8e03ad1ed6dee2e1b09e03dfee6c15e59b4f8311c882a9b95e19c5cdb88d90c8
7
- data.tar.gz: 241814297de25974719b07d728fb236df4b3de062997c033d50e79223bbb0609bb331f45d563efc8206ded3b0d2722583bb87e1b160a0e8a5a8744b0838a57ca
6
+ metadata.gz: 3f557376e9db220197b6f6f99cd28621593ed3a5f0bc96e26c471fb40b7b54e3f79564cad661873b223c7688713112bbf5536b705efdb0d3aa4b86d88725cd6b
7
+ data.tar.gz: d497420735d0567a167290a9de4130d66635f4ef36d5b1f674ca77e0320956518014cbc91054d72b10dc16ef3c2edc5498e47dd7a1b6ddce4edb013a757158ff
@@ -1,7 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
- - "2.1.0"
4
- - "2.0.0"
5
- - "1.9.3"
3
+ - 2.1.0
4
+ - 2.0.0
5
+ - 1.9.3
6
6
  services:
7
7
  - rabbitmq
@@ -1,4 +1,16 @@
1
- ## 0.9.0 — unreleased
1
+ ## 0.10.0 — unreleased
2
+
3
+ ### Bunny Update
4
+
5
+ Bunny is updated to `1.4.x`.
6
+
7
+ ### Exceptions in Error Handlers Don't Prevent Nacks
8
+
9
+ Exceptions in error handlers no longer prevent messages from being
10
+ `basic.nack`-ed.
11
+
12
+
13
+ ## 0.9.0 — May 13, 2014
2
14
 
3
15
  ### Platform-aware Signal Registration
4
16
 
@@ -1,10 +1,10 @@
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.2.1'
4
+ gem.add_runtime_dependency 'bunny', '>= 1.5.1'
5
5
  gem.add_runtime_dependency 'carrot-top', '~> 0.0.7'
6
6
  gem.add_runtime_dependency 'multi_json', '~> 1.5'
7
- gem.add_development_dependency 'rspec', '~> 2.12.0'
7
+ gem.add_development_dependency 'rspec', '~> 3.0'
8
8
  gem.add_development_dependency 'simplecov', '~> 0.7.1'
9
9
 
10
10
  gem.name = 'hutch'
@@ -19,8 +19,11 @@ module Hutch
19
19
  set_up_api_connection if options.fetch(:enable_http_api_use, true)
20
20
 
21
21
  if block_given?
22
- yield
23
- disconnect
22
+ begin
23
+ yield
24
+ ensure
25
+ disconnect
26
+ end
24
27
  end
25
28
  end
26
29
 
@@ -46,6 +49,16 @@ module Hutch
46
49
  end
47
50
 
48
51
  def open_connection!
52
+ if @config[:uri] && !@config[:uri].empty?
53
+ u = URI.parse(@config[:uri])
54
+
55
+ @config[:mq_host] = u.host
56
+ @config[:mq_port] = u.port
57
+ @config[:mq_vhost] = u.path.sub(/^\//, "")
58
+ @config[:mq_username] = u.user
59
+ @config[:mq_password] = u.password
60
+ end
61
+
49
62
  host = @config[:mq_host]
50
63
  port = @config[:mq_port]
51
64
  vhost = @config[:mq_vhost]
@@ -57,7 +70,6 @@ module Hutch
57
70
  protocol = tls ? "amqps://" : "amqp://"
58
71
  sanitized_uri = "#{protocol}#{username}@#{host}:#{port}/#{vhost.sub(/^\//, '')}"
59
72
  logger.info "connecting to rabbitmq (#{sanitized_uri})"
60
-
61
73
  @connection = Bunny.new(host: host, port: port, vhost: vhost,
62
74
  tls: tls, tls_key: tls_key, tls_cert: tls_cert,
63
75
  username: username, password: password,
@@ -68,6 +80,7 @@ module Hutch
68
80
  @connection.start
69
81
  end
70
82
 
83
+ logger.info "connected to RabbitMQ at #{host} as #{username}"
71
84
  @connection
72
85
  end
73
86
 
@@ -148,6 +161,14 @@ module Hutch
148
161
  @channel.work_pool.kill
149
162
  end
150
163
 
164
+ def requeue(delivery_tag)
165
+ @channel.reject(delivery_tag, true)
166
+ end
167
+
168
+ def reject(delivery_tag, requeue=false)
169
+ @channel.reject(delivery_tag, requeue)
170
+ end
171
+
151
172
  def ack(delivery_tag)
152
173
  @channel.ack(delivery_tag, false)
153
174
  end
@@ -12,7 +12,11 @@ module Hutch
12
12
  def run(argv = ARGV)
13
13
  parse_options(argv)
14
14
 
15
- Hutch.logger.info "hutch booted with pid #{Process.pid}"
15
+ ::Process.daemon(true) if Hutch::Config.daemonise
16
+
17
+ write_pid if Hutch::Config.pidfile
18
+
19
+ Hutch.logger.info "hutch booted with pid #{::Process.pid}"
16
20
 
17
21
  if load_app && start_work_loop == :success
18
22
  # If we got here, the worker was shut down nicely
@@ -170,6 +174,14 @@ module Hutch
170
174
  Hutch::Config.namespace = namespace
171
175
  end
172
176
 
177
+ opts.on('-d', '--daemonise', 'Daemonise') do |daemonise|
178
+ Hutch::Config.daemonise = daemonise
179
+ end
180
+
181
+ opts.on('--pidfile PIDFILE', 'Pidfile') do |pidfile|
182
+ Hutch::Config.pidfile = pidfile
183
+ end
184
+
173
185
  opts.on('--version', 'Print the version and exit') do
174
186
  puts "hutch v#{VERSION}"
175
187
  exit 0
@@ -181,5 +193,12 @@ module Hutch
181
193
  end
182
194
  end.parse!(args)
183
195
  end
196
+
197
+ def write_pid
198
+ pidfile = File.expand_path(Hutch::Config.pidfile)
199
+ Hutch.logger.info "writing pid in #{pidfile}"
200
+ File.open(pidfile, 'w') { |f| f.puts ::Process.pid }
201
+ end
202
+
184
203
  end
185
204
  end
@@ -7,7 +7,7 @@ module Hutch
7
7
  module Config
8
8
  require 'yaml'
9
9
 
10
- def self.initialize
10
+ def self.initialize(params={})
11
11
  @config = {
12
12
  mq_host: 'localhost',
13
13
  mq_port: 5672,
@@ -21,13 +21,18 @@ module Hutch
21
21
  mq_api_host: 'localhost',
22
22
  mq_api_port: 15672,
23
23
  mq_api_ssl: false,
24
+ # placeholder, allows specifying connection parameters
25
+ # as a URI.
26
+ uri: nil,
24
27
  log_level: Logger::INFO,
25
28
  require_paths: [],
26
29
  autoload_rails: true,
27
30
  error_handlers: [Hutch::ErrorHandlers::Logger.new],
28
31
  namespace: nil,
32
+ daemonise: false,
33
+ pidfile: nil,
29
34
  channel_prefetch: 0
30
- }
35
+ }.merge(params)
31
36
  end
32
37
 
33
38
  def self.get(attr)
@@ -5,11 +5,21 @@ module Hutch
5
5
  # gain a class method called `consume`, which should be used to register
6
6
  # the routing keys a consumer is interested in.
7
7
  module Consumer
8
+ attr_accessor :broker, :delivery_info
9
+
8
10
  def self.included(base)
9
11
  base.extend(ClassMethods)
10
12
  Hutch.register_consumer(base)
11
13
  end
12
14
 
15
+ def reject!
16
+ broker.reject(delivery_info.delivery_tag)
17
+ end
18
+
19
+ def requeue!
20
+ broker.requeue(delivery_info.delivery_tag)
21
+ end
22
+
13
23
  module ClassMethods
14
24
  # Add one or more routing keys to the set of routing keys the consumer
15
25
  # wants to subscribe to.
@@ -5,7 +5,7 @@ module Hutch
5
5
  class Logger
6
6
  include Logging
7
7
 
8
- def handle(message_id, consumer, ex)
8
+ def handle(message_id, payload, consumer, ex)
9
9
  prefix = "message(#{message_id || '-'}): "
10
10
  logger.error prefix + "error in consumer '#{consumer}'"
11
11
  logger.error prefix + "#{ex.class} - #{ex.message}"
@@ -12,7 +12,7 @@ module Hutch
12
12
  end
13
13
  end
14
14
 
15
- def handle(message_id, consumer, ex)
15
+ def handle(message_id, payload, consumer, ex)
16
16
  prefix = "message(#{message_id || '-'}): "
17
17
  logger.error prefix + "Logging event to Sentry"
18
18
  logger.error prefix + "#{ex.class} - #{ex.message}"
@@ -5,6 +5,8 @@ module Hutch
5
5
  class Message
6
6
  extend Forwardable
7
7
 
8
+ attr_reader :delivery_info, :properties, :payload
9
+
8
10
  def initialize(delivery_info, properties, payload)
9
11
  @delivery_info = delivery_info
10
12
  @properties = properties
@@ -1,4 +1,4 @@
1
1
  module Hutch
2
- VERSION = '0.9.0'.freeze
2
+ VERSION = '0.10.0'.freeze
3
3
  end
4
4
 
@@ -81,17 +81,17 @@ module Hutch
81
81
  broker = @broker
82
82
  begin
83
83
  message = Message.new(delivery_info, properties, payload)
84
- consumer.new.process(message)
84
+ consumer.new.tap { |c| c.broker, c.delivery_info = @broker, delivery_info }.process(message)
85
85
  broker.ack(delivery_info.delivery_tag)
86
86
  rescue StandardError => ex
87
- handle_error(properties.message_id, consumer, ex)
88
87
  broker.nack(delivery_info.delivery_tag)
88
+ handle_error(properties.message_id, payload, consumer, ex)
89
89
  end
90
90
  end
91
91
 
92
- def handle_error(message_id, consumer, ex)
92
+ def handle_error(message_id, payload, consumer, ex)
93
93
  Hutch::Config[:error_handlers].each do |backend|
94
- backend.handle(message_id, consumer, ex)
94
+ backend.handle(message_id, payload, consumer, ex)
95
95
  end
96
96
  end
97
97
 
@@ -6,37 +6,48 @@ describe Hutch::Broker do
6
6
  subject(:broker) { Hutch::Broker.new(config) }
7
7
 
8
8
  describe '#connect' do
9
- before { broker.stub(:set_up_amqp_connection) }
10
- before { broker.stub(:set_up_api_connection) }
11
- before { broker.stub(:disconnect) }
9
+ before { allow(broker).to receive(:set_up_amqp_connection) }
10
+ before { allow(broker).to receive(:set_up_api_connection) }
11
+ before { allow(broker).to receive(:disconnect) }
12
12
 
13
13
  it 'sets up the amqp connection' do
14
- broker.should_receive(:set_up_amqp_connection)
14
+ expect(broker).to receive(:set_up_amqp_connection)
15
15
  broker.connect
16
16
  end
17
17
 
18
18
  it 'sets up the api connection' do
19
- broker.should_receive(:set_up_api_connection)
19
+ expect(broker).to receive(:set_up_api_connection)
20
20
  broker.connect
21
21
  end
22
22
 
23
23
  it 'does not disconnect' do
24
- broker.should_not_receive(:disconnect)
24
+ expect(broker).not_to receive(:disconnect)
25
25
  broker.connect
26
26
  end
27
27
 
28
28
  context 'when given a block' do
29
29
  it 'disconnects' do
30
- broker.should_receive(:disconnect).once
30
+ expect(broker).to receive(:disconnect).once
31
31
  broker.connect { }
32
32
  end
33
33
  end
34
34
 
35
+ context 'when given a block that fails' do
36
+ let(:exception) { Class.new(StandardError) }
37
+
38
+ it 'disconnects' do
39
+ expect(broker).to receive(:disconnect).once
40
+ expect do
41
+ broker.connect { fail exception }
42
+ end.to raise_error(exception)
43
+ end
44
+ end
45
+
35
46
  context "with options" do
36
47
  let(:options) { { enable_http_api_use: false } }
37
48
 
38
49
  it "doesnt set up api" do
39
- broker.should_not_receive(:set_up_api_connection)
50
+ expect(broker).not_to receive(:set_up_api_connection)
40
51
  broker.connect options
41
52
  end
42
53
  end
@@ -47,16 +58,27 @@ describe Hutch::Broker do
47
58
  before { broker.set_up_amqp_connection }
48
59
  after { broker.disconnect }
49
60
 
50
- its(:connection) { should be_a Bunny::Session }
51
- its(:channel) { should be_a Bunny::Channel }
52
- its(:exchange) { should be_a Bunny::Exchange }
61
+ describe '#connection' do
62
+ subject { super().connection }
63
+ it { is_expected.to be_a Bunny::Session }
64
+ end
65
+
66
+ describe '#channel' do
67
+ subject { super().channel }
68
+ it { is_expected.to be_a Bunny::Channel }
69
+ end
70
+
71
+ describe '#exchange' do
72
+ subject { super().exchange }
73
+ it { is_expected.to be_a Bunny::Exchange }
74
+ end
53
75
  end
54
76
 
55
77
  context 'when given invalid details' do
56
78
  before { config[:mq_host] = 'notarealhost' }
57
79
  let(:set_up_amqp_connection) { ->{ broker.set_up_amqp_connection } }
58
80
 
59
- specify { set_up_amqp_connection.should raise_error }
81
+ specify { expect(set_up_amqp_connection).to raise_error }
60
82
  end
61
83
 
62
84
  context 'with channel_prefetch set' do
@@ -65,7 +87,8 @@ describe Hutch::Broker do
65
87
  after { broker.disconnect }
66
88
 
67
89
  it "set's channel's prefetch" do
68
- Bunny::Channel.any_instance.should_receive(:prefetch).with(prefetch_value)
90
+ expect_any_instance_of(Bunny::Channel).
91
+ to receive(:prefetch).with(prefetch_value)
69
92
  broker.set_up_amqp_connection
70
93
  end
71
94
  end
@@ -76,7 +99,10 @@ describe Hutch::Broker do
76
99
  before { broker.set_up_api_connection }
77
100
  after { broker.disconnect }
78
101
 
79
- its(:api_client) { should be_a CarrotTop }
102
+ describe '#api_client' do
103
+ subject { super().api_client }
104
+ it { is_expected.to be_a CarrotTop }
105
+ end
80
106
  end
81
107
 
82
108
  context 'when given invalid details' do
@@ -84,17 +110,19 @@ describe Hutch::Broker do
84
110
  after { broker.disconnect }
85
111
  let(:set_up_api_connection) { ->{ broker.set_up_api_connection } }
86
112
 
87
- specify { set_up_api_connection.should raise_error }
113
+ specify { expect(set_up_api_connection).to raise_error }
88
114
  end
89
115
  end
90
116
 
91
117
  describe '#queue' do
92
118
  let(:channel) { double('Channel') }
93
- before { broker.stub(:channel) { channel } }
119
+ before { allow(broker).to receive(:channel) { channel } }
94
120
 
95
121
  it 'applies a global namespace' do
96
122
  config[:namespace] = 'mirror-all.service'
97
- broker.channel.should_receive(:queue).with { |*args| args.first == 'mirror-all.service:test' }
123
+ expect(broker.channel).to receive(:queue) do |*args|
124
+ args.first == 'mirror-all.service:test'
125
+ end
98
126
  broker.queue('test')
99
127
  end
100
128
  end
@@ -104,7 +132,10 @@ describe Hutch::Broker do
104
132
  subject { broker.bindings }
105
133
 
106
134
  context 'with no bindings' do
107
- its(:keys) { should_not include 'test' }
135
+ describe '#keys' do
136
+ subject { super().keys }
137
+ it { is_expected.not_to include 'test' }
138
+ end
108
139
  end
109
140
 
110
141
  context 'with a binding' do
@@ -114,7 +145,7 @@ describe Hutch::Broker do
114
145
  queue.unbind(broker.exchange, routing_key: 'key').delete
115
146
  end
116
147
 
117
- it { should include({ 'test' => ['key'] }) }
148
+ it { is_expected.to include({ 'test' => ['key'] }) }
118
149
  end
119
150
  end
120
151
 
@@ -124,17 +155,17 @@ describe Hutch::Broker do
124
155
 
125
156
  let(:routing_keys) { %w( a b c ) }
126
157
  let(:queue) { double('Queue', bind: nil, unbind: nil, name: 'consumer') }
127
- before { broker.stub(bindings: { 'consumer' => ['d'] }) }
158
+ before { allow(broker).to receive(:bindings).and_return('consumer' => ['d']) }
128
159
 
129
160
  it 'calls bind for each routing key' do
130
161
  routing_keys.each do |key|
131
- queue.should_receive(:bind).with(broker.exchange, routing_key: key)
162
+ expect(queue).to receive(:bind).with(broker.exchange, routing_key: key)
132
163
  end
133
164
  broker.bind_queue(queue, routing_keys)
134
165
  end
135
166
 
136
167
  it 'calls unbind for each redundant existing binding' do
137
- queue.should_receive(:unbind).with(broker.exchange, routing_key: 'd')
168
+ expect(queue).to receive(:unbind).with(broker.exchange, routing_key: 'd')
138
169
  broker.bind_queue(queue, routing_keys)
139
170
  end
140
171
 
@@ -142,29 +173,29 @@ describe Hutch::Broker do
142
173
  let(:queue) { broker.queue('consumer') }
143
174
  let(:routing_key) { 'key' }
144
175
 
145
- before { broker.unstub(:bindings) }
176
+ before { allow(broker).to receive(:bindings).and_call_original }
146
177
  before { queue.bind(broker.exchange, routing_key: 'redundant-key') }
147
178
  after { queue.unbind(broker.exchange, routing_key: routing_key).delete }
148
179
 
149
180
  it 'results in the correct bindings' do
150
181
  broker.bind_queue(queue, [routing_key])
151
- broker.bindings.should include({ queue.name => [routing_key] })
182
+ expect(broker.bindings).to include({ queue.name => [routing_key] })
152
183
  end
153
184
  end
154
185
  end
155
186
 
156
187
  describe '#wait_on_threads' do
157
188
  let(:thread) { double('Thread') }
158
- before { broker.stub(work_pool_threads: threads) }
189
+ before { allow(broker).to receive(:work_pool_threads).and_return(threads) }
159
190
 
160
191
  context 'when all threads finish within the timeout' do
161
192
  let(:threads) { [double(join: thread), double(join: thread)] }
162
- specify { expect(broker.wait_on_threads(1)).to be_true }
193
+ specify { expect(broker.wait_on_threads(1)).to be_truthy }
163
194
  end
164
195
 
165
196
  context 'when timeout expires for one thread' do
166
197
  let(:threads) { [double(join: thread), double(join: nil)] }
167
- specify { expect(broker.wait_on_threads(1)).to be_false }
198
+ specify { expect(broker.wait_on_threads(1)).to be_falsey }
168
199
  end
169
200
  end
170
201
 
@@ -174,12 +205,12 @@ describe Hutch::Broker do
174
205
  after { broker.disconnect }
175
206
 
176
207
  it 'publishes to the exchange' do
177
- broker.exchange.should_receive(:publish).once
208
+ expect(broker.exchange).to receive(:publish).once
178
209
  broker.publish('test.key', 'message')
179
210
  end
180
211
 
181
212
  it 'sets default properties' do
182
- broker.exchange.should_receive(:publish).with(
213
+ expect(broker.exchange).to receive(:publish).with(
183
214
  JSON.dump("message"),
184
215
  hash_including(
185
216
  persistent: true,
@@ -192,29 +223,31 @@ describe Hutch::Broker do
192
223
  end
193
224
 
194
225
  it 'allows passing message properties' do
195
- broker.exchange.should_receive(:publish).once
226
+ expect(broker.exchange).to receive(:publish).once
196
227
  broker.publish('test.key', 'message', {expiration: "2000", persistent: false})
197
228
  end
198
229
 
199
230
  context 'when there are global properties' do
200
231
  context 'as a hash' do
201
232
  before do
202
- Hutch.stub global_properties: { app_id: 'app' }
233
+ allow(Hutch).to receive(:global_properties).and_return(app_id: 'app')
203
234
  end
204
235
 
205
236
  it 'merges the properties' do
206
- broker.exchange.should_receive(:publish).with('"message"', hash_including(app_id: 'app'))
237
+ expect(broker.exchange).
238
+ to receive(:publish).with('"message"', hash_including(app_id: 'app'))
207
239
  broker.publish('test.key', 'message')
208
240
  end
209
241
  end
210
242
 
211
243
  context 'as a callable object' do
212
244
  before do
213
- Hutch.stub global_properties: proc { { app_id: 'app' } }
245
+ allow(Hutch).to receive(:global_properties).and_return(proc { { app_id: 'app' } })
214
246
  end
215
247
 
216
248
  it 'calls the proc and merges the properties' do
217
- broker.exchange.should_receive(:publish).with('"message"', hash_including(app_id: 'app'))
249
+ expect(broker.exchange).
250
+ to receive(:publish).with('"message"', hash_including(app_id: 'app'))
218
251
  broker.publish('test.key', 'message')
219
252
  end
220
253
  end
@@ -228,7 +261,7 @@ describe Hutch::Broker do
228
261
  end
229
262
 
230
263
  it 'logs an error' do
231
- broker.logger.should_receive(:error)
264
+ expect(broker.logger).to receive(:error)
232
265
  broker.publish('test.key', 'message') rescue nil
233
266
  end
234
267
  end
@@ -8,7 +8,7 @@ describe Hutch::CLI do
8
8
  context "--config" do
9
9
  context "when the config file does not exist" do
10
10
  let(:file) { "/path/to/nonexistant/file" }
11
- before { STDERR.stub(:write) }
11
+ before { allow(STDERR).to receive(:write) }
12
12
 
13
13
  it "bails" do
14
14
  expect {
@@ -23,7 +23,7 @@ describe Hutch::CLI do
23
23
  end
24
24
 
25
25
  it "parses the config" do
26
- Hutch::Config.should_receive(:load_from_file)
26
+ expect(Hutch::Config).to receive(:load_from_file)
27
27
  cli.parse_options(["--config=#{file}"])
28
28
  end
29
29
  end
@@ -32,7 +32,7 @@ describe Hutch::CLI do
32
32
  context "--mq-tls-key" do
33
33
  context "when the keyfile file does not exist" do
34
34
  let(:file) { "/path/to/nonexistant/file" }
35
- before { STDERR.stub(:write) }
35
+ before { allow(STDERR).to receive(:write) }
36
36
 
37
37
  it "bails" do
38
38
  expect {
@@ -47,7 +47,7 @@ describe Hutch::CLI do
47
47
  end
48
48
 
49
49
  it "sets mq_tls_key to the file" do
50
- Hutch::Config.should_receive(:mq_tls_key=)
50
+ expect(Hutch::Config).to receive(:mq_tls_key=)
51
51
  cli.parse_options(["--mq-tls-key=#{file}"])
52
52
  end
53
53
  end
@@ -56,7 +56,7 @@ describe Hutch::CLI do
56
56
  context "--mq-tls-cert" do
57
57
  context "when the certfile file does not exist" do
58
58
  let(:file) { "/path/to/nonexistant/file" }
59
- before { STDERR.stub(:write) }
59
+ before { allow(STDERR).to receive(:write) }
60
60
 
61
61
  it "bails" do
62
62
  expect {
@@ -71,7 +71,7 @@ describe Hutch::CLI do
71
71
  end
72
72
 
73
73
  it "sets mq_tls_cert to the file" do
74
- Hutch::Config.should_receive(:mq_tls_cert=)
74
+ expect(Hutch::Config).to receive(:mq_tls_cert=)
75
75
  cli.parse_options(["--mq-tls-cert=#{file}"])
76
76
  end
77
77
  end
@@ -9,18 +9,18 @@ describe Hutch::Config do
9
9
  subject { Hutch::Config.get(:mq_host) }
10
10
 
11
11
  context 'with no overridden value' do
12
- it { should == 'localhost' }
12
+ it { is_expected.to eq('localhost') }
13
13
  end
14
14
 
15
15
  context 'with an overridden value' do
16
- before { Hutch::Config.stub(user_config: { mq_host: new_value }) }
17
- it { should == new_value }
16
+ before { allow(Hutch::Config).to receive_messages(user_config: { mq_host: new_value }) }
17
+ it { is_expected.to eq(new_value) }
18
18
  end
19
19
  end
20
20
 
21
21
  context 'for invalid attributes' do
22
22
  let(:invalid_get) { ->{ Hutch::Config.get(:invalid_attr) } }
23
- specify { invalid_get.should raise_error Hutch::UnknownAttributeError }
23
+ specify { expect(invalid_get).to raise_error Hutch::UnknownAttributeError }
24
24
  end
25
25
  end
26
26
 
@@ -30,41 +30,41 @@ describe Hutch::Config do
30
30
  subject { Hutch::Config.user_config[:mq_host] }
31
31
 
32
32
  context 'sets value in user config hash' do
33
- it { should == new_value }
33
+ it { is_expected.to eq(new_value) }
34
34
  end
35
35
  end
36
36
 
37
37
  context 'for invalid attributes' do
38
38
  let(:invalid_set) { ->{ Hutch::Config.set(:invalid_attr, new_value) } }
39
- specify { invalid_set.should raise_error Hutch::UnknownAttributeError }
39
+ specify { expect(invalid_set).to raise_error Hutch::UnknownAttributeError }
40
40
  end
41
41
  end
42
42
 
43
43
  describe 'a magic getter' do
44
44
  context 'for a valid attribute' do
45
45
  it 'calls get' do
46
- Hutch::Config.should_receive(:get).with(:mq_host)
46
+ expect(Hutch::Config).to receive(:get).with(:mq_host)
47
47
  Hutch::Config.mq_host
48
48
  end
49
49
  end
50
50
 
51
51
  context 'for an invalid attribute' do
52
52
  let(:invalid_getter) { ->{ Hutch::Config.invalid_attr } }
53
- specify { invalid_getter.should raise_error NoMethodError }
53
+ specify { expect(invalid_getter).to raise_error NoMethodError }
54
54
  end
55
55
  end
56
56
 
57
57
  describe 'a magic setter' do
58
58
  context 'for a valid attribute' do
59
59
  it 'calls set' do
60
- Hutch::Config.should_receive(:set).with(:mq_host, new_value)
60
+ expect(Hutch::Config).to receive(:set).with(:mq_host, new_value)
61
61
  Hutch::Config.mq_host = new_value
62
62
  end
63
63
  end
64
64
 
65
65
  context 'for an invalid attribute' do
66
66
  let(:invalid_setter) { ->{ Hutch::Config.invalid_attr = new_value } }
67
- specify { invalid_setter.should raise_error NoMethodError }
67
+ specify { expect(invalid_setter).to raise_error NoMethodError }
68
68
  end
69
69
  end
70
70
 
@@ -92,8 +92,8 @@ describe Hutch::Config do
92
92
 
93
93
  it 'loads in the config data' do
94
94
  Hutch::Config.load_from_file(file)
95
- Hutch::Config.mq_host.should eq host
96
- Hutch::Config.mq_username.should eq username
95
+ expect(Hutch::Config.mq_host).to eq host
96
+ expect(Hutch::Config.mq_username).to eq username
97
97
  end
98
98
  end
99
99
  end
@@ -29,8 +29,8 @@ describe Hutch::Consumer do
29
29
 
30
30
  describe 'module inclusion' do
31
31
  it 'registers the class as a consumer' do
32
- Hutch.should_receive(:register_consumer) do |klass|
33
- klass.should == simple_consumer
32
+ expect(Hutch).to receive(:register_consumer) do |klass|
33
+ expect(klass).to eq(simple_consumer)
34
34
  end
35
35
 
36
36
  simple_consumer
@@ -40,20 +40,24 @@ describe Hutch::Consumer do
40
40
 
41
41
  describe '.consume' do
42
42
  it 'saves the routing key to the consumer' do
43
- simple_consumer.routing_keys.should include 'hutch.test1'
43
+ expect(simple_consumer.routing_keys).to include 'hutch.test1'
44
44
  end
45
45
 
46
46
  context 'with multiple routing keys' do
47
47
  it 'registers the class once for each routing key' do
48
- complex_consumer.routing_keys.should include 'hutch.test1'
49
- complex_consumer.routing_keys.should include 'hutch.test2'
48
+ expect(complex_consumer.routing_keys).to include 'hutch.test1'
49
+ expect(complex_consumer.routing_keys).to include 'hutch.test2'
50
50
  end
51
51
  end
52
52
 
53
53
  context 'when given the same routing key multiple times' do
54
54
  subject { simple_consumer.routing_keys }
55
55
  before { simple_consumer.consume 'hutch.test1' }
56
- its(:length) { should == 1}
56
+
57
+ describe '#length' do
58
+ subject { super().length }
59
+ it { is_expected.to eq(1)}
60
+ end
57
61
  end
58
62
  end
59
63
 
@@ -72,7 +76,7 @@ describe Hutch::Consumer do
72
76
  queue_name "bar"
73
77
  end
74
78
 
75
- Foo.get_queue_name.should == "bar"
79
+ expect(Foo.get_queue_name).to eq("bar")
76
80
  end
77
81
  end
78
82
 
@@ -84,7 +88,7 @@ describe Hutch::Consumer do
84
88
  end
85
89
  end
86
90
 
87
- Foo::Bar.get_queue_name.should == 'foo:bar'
91
+ expect(Foo::Bar.get_queue_name).to eq('foo:bar')
88
92
  end
89
93
 
90
94
  it 'converts camelcase class names to snake case' do
@@ -92,7 +96,7 @@ describe Hutch::Consumer do
92
96
  include Hutch::Consumer
93
97
  end
94
98
 
95
- FooBarBAZ.get_queue_name.should == 'foo_bar_baz'
99
+ expect(FooBarBAZ.get_queue_name).to eq('foo_bar_baz')
96
100
  end
97
101
  end
98
102
  end
@@ -4,12 +4,12 @@ describe Hutch::ErrorHandlers::Logger do
4
4
  let(:error_handler) { Hutch::ErrorHandlers::Logger.new }
5
5
 
6
6
  describe '#handle' do
7
- let(:error) { stub(message: "Stuff went wrong", class: "RuntimeError",
7
+ let(:error) { double(message: "Stuff went wrong", class: "RuntimeError",
8
8
  backtrace: ["line 1", "line 2"]) }
9
9
 
10
10
  it "logs three separate lines" do
11
- Hutch::Logging.logger.should_receive(:error).exactly(3).times
12
- error_handler.handle("1", stub, error)
11
+ expect(Hutch::Logging.logger).to receive(:error).exactly(3).times
12
+ error_handler.handle("1", "{}", double, error)
13
13
  end
14
14
  end
15
15
  end
@@ -13,8 +13,8 @@ describe Hutch::ErrorHandlers::Sentry do
13
13
  end
14
14
 
15
15
  it "logs the error to Sentry" do
16
- Raven.should_receive(:capture_exception).with(error)
17
- error_handler.handle("1", stub, error)
16
+ expect(Raven).to receive(:capture_exception).with(error)
17
+ error_handler.handle("1", "{}", double, error)
18
18
  end
19
19
  end
20
20
  end
@@ -11,16 +11,16 @@ describe Hutch::Logging do
11
11
  context 'with the default logger' do
12
12
  subject { Hutch::Logging.logger }
13
13
 
14
- it { should be_instance_of(Logger) }
14
+ it { is_expected.to be_instance_of(Logger) }
15
15
  end
16
16
 
17
17
  context 'with a custom logger' do
18
- let(:dummy_logger) { mock("Dummy logger", warn: true, info: true) }
18
+ let(:dummy_logger) { double("Dummy logger", warn: true, info: true) }
19
19
  after { Hutch::Logging.setup_logger }
20
20
 
21
21
  it "users the custom logger" do
22
22
  Hutch::Logging.logger = dummy_logger
23
- Hutch::Logging.logger.should == dummy_logger
23
+ expect(Hutch::Logging.logger).to eq(dummy_logger)
24
24
  end
25
25
  end
26
26
  end
@@ -7,17 +7,20 @@ describe Hutch::Message do
7
7
  let(:json_body) { MultiJson.dump(body) }
8
8
  subject(:message) { Hutch::Message.new(delivery_info, props, json_body) }
9
9
 
10
- its(:body) { should == body }
10
+ describe '#body' do
11
+ subject { super().body }
12
+ it { is_expected.to eq(body) }
13
+ end
11
14
 
12
15
  describe '[]' do
13
16
  subject { message[:foo] }
14
- it { should == 'bar' }
17
+ it { is_expected.to eq('bar') }
15
18
  end
16
19
 
17
20
  [:message_id, :timestamp].each do |method|
18
21
  describe method.to_s do
19
22
  it 'delegates to @properties' do
20
- props.should_receive(method)
23
+ expect(props).to receive(method)
21
24
  message.send(method)
22
25
  end
23
26
  end
@@ -26,7 +29,7 @@ describe Hutch::Message do
26
29
  [:routing_key, :exchange].each do |method|
27
30
  describe method.to_s do
28
31
  it 'delegates to @delivery_info' do
29
- delivery_info.should_receive(method)
32
+ expect(delivery_info).to receive(method)
30
33
  message.send(method)
31
34
  end
32
35
  end
@@ -2,7 +2,6 @@ require 'spec_helper'
2
2
  require 'hutch/worker'
3
3
 
4
4
  describe Hutch::Worker do
5
- before { Raven.as_null_object }
6
5
  let(:consumer) { double('Consumer', routing_keys: %w( a b c ),
7
6
  get_queue_name: 'consumer') }
8
7
  let(:consumers) { [consumer, double('Consumer')] }
@@ -12,7 +11,7 @@ describe Hutch::Worker do
12
11
  describe '#setup_queues' do
13
12
  it 'sets up queues for each of the consumers' do
14
13
  consumers.each do |consumer|
15
- worker.should_receive(:setup_queue).with(consumer)
14
+ expect(worker).to receive(:setup_queue).with(consumer)
16
15
  end
17
16
  worker.setup_queues
18
17
  end
@@ -20,21 +19,21 @@ describe Hutch::Worker do
20
19
 
21
20
  describe '#setup_queue' do
22
21
  let(:queue) { double('Queue', bind: nil, subscribe: nil) }
23
- before { worker.stub(consumer_queue: queue) }
24
- before { broker.stub(queue: queue, bind_queue: nil) }
22
+ before { allow(worker).to receive_messages(consumer_queue: queue) }
23
+ before { allow(broker).to receive_messages(queue: queue, bind_queue: nil) }
25
24
 
26
25
  it 'creates a queue' do
27
- broker.should_receive(:queue).with(consumer.get_queue_name).and_return(queue)
26
+ expect(broker).to receive(:queue).with(consumer.get_queue_name).and_return(queue)
28
27
  worker.setup_queue(consumer)
29
28
  end
30
29
 
31
30
  it 'binds the queue to each of the routing keys' do
32
- broker.should_receive(:bind_queue).with(queue, %w( a b c ))
31
+ expect(broker).to receive(:bind_queue).with(queue, %w( a b c ))
33
32
  worker.setup_queue(consumer)
34
33
  end
35
34
 
36
35
  it 'sets up a subscription' do
37
- queue.should_receive(:subscribe).with(ack: true)
36
+ expect(queue).to receive(:subscribe).with(ack: true)
38
37
  worker.setup_queue(consumer)
39
38
  end
40
39
  end
@@ -45,34 +44,36 @@ describe Hutch::Worker do
45
44
  let(:delivery_info) { double('Delivery Info', routing_key: '',
46
45
  delivery_tag: 'dt') }
47
46
  let(:properties) { double('Properties', message_id: nil) }
48
- before { consumer.stub(new: consumer_instance) }
49
- before { broker.stub(:ack) }
50
- before { broker.stub(:nack) }
47
+ before { allow(consumer).to receive_messages(new: consumer_instance) }
48
+ before { allow(broker).to receive(:ack) }
49
+ before { allow(broker).to receive(:nack) }
50
+ before { allow(consumer_instance).to receive(:broker=) }
51
+ before { allow(consumer_instance).to receive(:delivery_info=) }
51
52
 
52
53
  it 'passes the message to the consumer' do
53
- consumer_instance.should_receive(:process).
54
+ expect(consumer_instance).to receive(:process).
54
55
  with(an_instance_of(Hutch::Message))
55
56
  worker.handle_message(consumer, delivery_info, properties, payload)
56
57
  end
57
58
 
58
59
  it 'acknowledges the message' do
59
- consumer_instance.stub(:process)
60
- broker.should_receive(:ack).with(delivery_info.delivery_tag)
60
+ allow(consumer_instance).to receive(:process)
61
+ expect(broker).to receive(:ack).with(delivery_info.delivery_tag)
61
62
  worker.handle_message(consumer, delivery_info, properties, payload)
62
63
  end
63
64
 
64
65
  context 'when the consumer raises an exception' do
65
- before { consumer_instance.stub(:process).and_raise('a consumer error') }
66
+ before { allow(consumer_instance).to receive(:process).and_raise('a consumer error') }
66
67
 
67
68
  it 'logs the error' do
68
69
  Hutch::Config[:error_handlers].each do |backend|
69
- backend.should_receive(:handle)
70
+ expect(backend).to receive(:handle)
70
71
  end
71
72
  worker.handle_message(consumer, delivery_info, properties, payload)
72
73
  end
73
74
 
74
75
  it 'rejects the message' do
75
- broker.should_receive(:nack).with(delivery_info.delivery_tag)
76
+ expect(broker).to receive(:nack).with(delivery_info.delivery_tag)
76
77
  worker.handle_message(consumer, delivery_info, properties, payload)
77
78
  end
78
79
  end
@@ -82,13 +83,13 @@ describe Hutch::Worker do
82
83
 
83
84
  it 'logs the error' do
84
85
  Hutch::Config[:error_handlers].each do |backend|
85
- backend.should_receive(:handle)
86
+ expect(backend).to receive(:handle)
86
87
  end
87
88
  worker.handle_message(consumer, delivery_info, properties, payload)
88
89
  end
89
90
 
90
91
  it 'rejects the message' do
91
- broker.should_receive(:nack).with(delivery_info.delivery_tag)
92
+ expect(broker).to receive(:nack).with(delivery_info.delivery_tag)
92
93
  worker.handle_message(consumer, delivery_info, properties, payload)
93
94
  end
94
95
  end
@@ -8,8 +8,8 @@ describe Hutch do
8
8
  it 'saves the consumers in the global consumer list' do
9
9
  Hutch.register_consumer(consumer_a)
10
10
  Hutch.register_consumer(consumer_b)
11
- Hutch.consumers.should include consumer_a
12
- Hutch.consumers.should include consumer_b
11
+ expect(Hutch.consumers).to include consumer_a
12
+ expect(Hutch.consumers).to include consumer_b
13
13
  end
14
14
  end
15
15
 
@@ -21,8 +21,8 @@ describe Hutch do
21
21
  let(:action) { Hutch.connect(options, config) }
22
22
 
23
23
  it 'passes options and config' do
24
- Hutch::Broker.should_receive(:new).with(config).and_return broker
25
- broker.should_receive(:connect).with options
24
+ expect(Hutch::Broker).to receive(:new).with(config).and_return broker
25
+ expect(broker).to receive(:connect).with options
26
26
 
27
27
  action
28
28
  end
@@ -30,15 +30,15 @@ describe Hutch do
30
30
  it 'sets @connect' do
31
31
  action
32
32
 
33
- expect(Hutch.connected?).to be_true
33
+ expect(Hutch.connected?).to be_truthy
34
34
  end
35
35
  end
36
36
 
37
37
  context 'connected' do
38
- before { Hutch.stub(:connected?).and_return true }
38
+ before { allow(Hutch).to receive(:connected?).and_return true }
39
39
 
40
40
  it 'does not reconnect' do
41
- Hutch::Broker.should_not_receive :new
41
+ expect(Hutch::Broker).not_to receive :new
42
42
  Hutch.connect
43
43
  end
44
44
  end
@@ -48,12 +48,10 @@ describe Hutch do
48
48
  let(:broker) { double(Hutch::Broker) }
49
49
  let(:args) { ['test.key', 'message', { headers: { foo: 'bar' } }] }
50
50
 
51
- before do
52
- Hutch.stub broker: broker
53
- end
51
+ before { allow(Hutch).to receive(:broker).and_return(broker) }
54
52
 
55
53
  it 'delegates to Hutch::Broker#publish' do
56
- broker.should_receive(:publish).with(*args)
54
+ expect(broker).to receive(:publish).with(*args)
57
55
  Hutch.publish(*args)
58
56
  end
59
57
  end
@@ -15,6 +15,7 @@ require 'logger'
15
15
 
16
16
  RSpec.configure do |config|
17
17
  config.before(:all) { Hutch::Config.log_level = Logger::FATAL }
18
+ config.raise_errors_for_deprecations!
18
19
  end
19
20
 
20
21
  # Constants (classes, etc) defined within a block passed to this method
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hutch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.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-05-13 00:00:00.000000000 Z
11
+ date: 2014-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
- version: 1.2.1
19
+ version: 1.5.1
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.2.1
26
+ version: 1.5.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: carrot-top
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 2.12.0
61
+ version: '3.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: 2.12.0
68
+ version: '3.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: simplecov
71
71
  requirement: !ruby/object:Gem::Requirement