hutch 1.1.1 → 1.3.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/.github/workflows/test.yml +21 -7
- data/CHANGELOG.md +20 -0
- data/Gemfile +8 -9
- data/README.md +8 -0
- data/bin/ci/before_build_docker.sh +0 -0
- data/hutch.gemspec +4 -4
- data/lib/hutch/broker.rb +6 -2
- data/lib/hutch/cli.rb +2 -2
- data/lib/hutch/config.rb +13 -1
- data/lib/hutch/consumer.rb +6 -0
- data/lib/hutch/error_handlers/sentry.rb +1 -1
- data/lib/hutch/tracers/datadog.rb +2 -1
- data/lib/hutch/version.rb +1 -1
- data/lib/hutch/worker.rb +3 -3
- data/spec/hutch/broker_spec.rb +4 -4
- data/spec/hutch/config_spec.rb +51 -17
- data/spec/hutch/error_handlers/bugsnag_spec.rb +1 -0
- data/spec/hutch/error_handlers/sentry_raven_spec.rb +1 -1
- data/spec/hutch/error_handlers/sentry_spec.rb +8 -0
- data/spec/hutch/tracers/datadog_spec.rb +5 -3
- data/spec/hutch/worker_spec.rb +57 -13
- metadata +8 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6d1384ceb1b05cbdb706ac6e0f4cd4bfbdd86a49cbc2b6f61dabf96c1ca80ab5
|
|
4
|
+
data.tar.gz: d83a7db8184ed5baa8c00649de3d62a711ee07c04a598802193c1f6d4f7c97c8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 703c57b0c1e7ab3774d2fae904b6e7aa84f98b8f512ce8676c8456e63a4da4b97ab8dd77a460353d88c39d95997c70ca19695f6710bbde1674e6a03aa70a222b
|
|
7
|
+
data.tar.gz: 9fea55e47720b5cf78f834d714a709ada538cb851edcb5f17fc9ad2b587f68dffcc5c5524c2855d9673da322378d4fda19d85554a90c3f1d993726f7790da912
|
data/.github/workflows/test.yml
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
name: Test
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
concurrency:
|
|
4
|
+
group: ${{ github.ref }}
|
|
5
|
+
cancel-in-progress: true
|
|
6
|
+
|
|
7
|
+
on: [push,pull_request,workflow_dispatch]
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
10
|
test:
|
|
@@ -22,10 +22,15 @@ jobs:
|
|
|
22
22
|
strategy:
|
|
23
23
|
fail-fast: false
|
|
24
24
|
matrix:
|
|
25
|
-
ruby-version:
|
|
25
|
+
ruby-version:
|
|
26
|
+
- '2.7'
|
|
27
|
+
- '3.0'
|
|
28
|
+
- '3.1'
|
|
29
|
+
- '3.2'
|
|
30
|
+
- '3.3'
|
|
26
31
|
|
|
27
32
|
steps:
|
|
28
|
-
- uses: actions/checkout@
|
|
33
|
+
- uses: actions/checkout@v4
|
|
29
34
|
- name: Set up Ruby
|
|
30
35
|
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
|
31
36
|
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
|
@@ -40,3 +45,12 @@ jobs:
|
|
|
40
45
|
./bin/ci/before_build_docker.sh
|
|
41
46
|
- name: Run tests
|
|
42
47
|
run: bundle exec rspec spec
|
|
48
|
+
test_all:
|
|
49
|
+
if: ${{ always() }}
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
name: Test (matrix)
|
|
52
|
+
needs: test
|
|
53
|
+
steps:
|
|
54
|
+
- name: Check test matrix status
|
|
55
|
+
if: ${{ needs.test.result != 'success' }}
|
|
56
|
+
run: exit 1
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
|
+
## 1.3.0 (Nov 11, 2024)
|
|
2
|
+
|
|
3
|
+
### Ruby 3.2 Compatibility
|
|
4
|
+
|
|
5
|
+
GitHub issue: [#392](https://github.com/ruby-amqp/hutch/pull/392)
|
|
6
|
+
|
|
7
|
+
### Relaxed ActiveSupport Dependency Constraints
|
|
8
|
+
|
|
9
|
+
Contributed by drobny.
|
|
10
|
+
|
|
11
|
+
GitHub issue: [#402](https://github.com/ruby-amqp/hutch/pull/402)
|
|
12
|
+
|
|
13
|
+
### Client-Provided Connection Name
|
|
14
|
+
|
|
15
|
+
Contributed by @sharshenov.
|
|
16
|
+
|
|
17
|
+
GitHub issue: [#399](https://github.com/ruby-amqp/hutch/pull/399)
|
|
18
|
+
|
|
19
|
+
|
|
1
20
|
## 1.1.1 (March 18th, 2022)
|
|
21
|
+
|
|
2
22
|
### Dependency Bump
|
|
3
23
|
|
|
4
24
|
Hutch now allows ActiveSupport 7.x.
|
data/Gemfile
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
|
-
ruby '>= 2.
|
|
3
|
+
ruby '>= 2.7.0'
|
|
4
4
|
|
|
5
5
|
gemspec
|
|
6
6
|
|
|
7
7
|
group :development do
|
|
8
8
|
gem "rake"
|
|
9
|
-
gem "guard", "~> 2.14", platform: :
|
|
10
|
-
gem "guard-rspec", "~> 4.7", platform: :
|
|
9
|
+
gem "guard", "~> 2.14", platform: :mri
|
|
10
|
+
gem "guard-rspec", "~> 4.7", platform: :mri
|
|
11
11
|
|
|
12
12
|
gem "yard", "~> 0.9"
|
|
13
13
|
gem 'kramdown', "> 0", platform: :jruby
|
|
@@ -16,21 +16,20 @@ group :development do
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
group :development, :test do
|
|
19
|
-
gem "rspec", "~> 3.
|
|
20
|
-
gem "simplecov", "~> 0.
|
|
19
|
+
gem "rspec", "~> 3.12"
|
|
20
|
+
gem "simplecov", "~> 0.21"
|
|
21
21
|
|
|
22
22
|
gem "sentry-raven"
|
|
23
23
|
gem "sentry-ruby"
|
|
24
24
|
gem "honeybadger"
|
|
25
|
-
gem "coveralls", "~> 0.8.15", require: false
|
|
26
25
|
gem "newrelic_rpm"
|
|
27
|
-
gem "ddtrace"
|
|
28
|
-
gem "airbrake", "~>
|
|
26
|
+
gem "ddtrace", "~> 1.8"
|
|
27
|
+
gem "airbrake", "~> 13.0"
|
|
29
28
|
gem "rollbar"
|
|
30
29
|
gem "bugsnag"
|
|
31
30
|
end
|
|
32
31
|
|
|
33
32
|
group :development, :darwin do
|
|
34
|
-
gem "rb-fsevent", "~> 0.
|
|
33
|
+
gem "rb-fsevent", "~> 0.11.2"
|
|
35
34
|
gem "growl", "~> 1.0.3"
|
|
36
35
|
end
|
data/README.md
CHANGED
|
@@ -406,6 +406,7 @@ Known configuration parameters are:
|
|
|
406
406
|
* `error_acknowledgements`: a chain of responsibility of objects that acknowledge/reject/requeue messages when an
|
|
407
407
|
exception happens, see classes in `Hutch::Acknowledgements`.
|
|
408
408
|
* `mq_exchange`: exchange to use for publishing (default: `hutch`)
|
|
409
|
+
* `mq_client_properties`: Bunny's [client properties](https://www.rabbitmq.com/docs/connections#capabilities) (default: `{}`)
|
|
409
410
|
* `heartbeat`: [RabbitMQ heartbeat timeout](http://rabbitmq.com/heartbeats.html) (default: `30`)
|
|
410
411
|
* `connection_timeout`: Bunny's socket open timeout (default: `11`)
|
|
411
412
|
* `read_timeout`: Bunny's socket read timeout (default: `11`)
|
|
@@ -542,6 +543,13 @@ Generate with
|
|
|
542
543
|
<td><tt>HUTCH_CHANNEL_PREFETCH</tt></td>
|
|
543
544
|
<td><p>The <tt>basic.qos</tt> prefetch value to use.</p></td>
|
|
544
545
|
</tr>
|
|
546
|
+
<tr>
|
|
547
|
+
<td><tt>connection_name</tt></td>
|
|
548
|
+
<td>nil</td>
|
|
549
|
+
<td>String</td>
|
|
550
|
+
<td><tt>HUTCH_CONNECTION_NAME</tt></td>
|
|
551
|
+
<td><p><a href="https://www.rabbitmq.com/docs/connections#client-provided-names">Client-Provided Connection Name</a></p></td>
|
|
552
|
+
</tr>
|
|
545
553
|
<tr>
|
|
546
554
|
<td><tt>connection_timeout</tt></td>
|
|
547
555
|
<td>11</td>
|
|
File without changes
|
data/hutch.gemspec
CHANGED
|
@@ -3,20 +3,20 @@ require File.expand_path('../lib/hutch/version', __FILE__)
|
|
|
3
3
|
Gem::Specification.new do |gem|
|
|
4
4
|
if defined?(JRUBY_VERSION)
|
|
5
5
|
gem.platform = 'java'
|
|
6
|
-
gem.add_runtime_dependency 'march_hare', '>=
|
|
6
|
+
gem.add_runtime_dependency 'march_hare', '>= 4.5.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.23', '< 3.0'
|
|
10
10
|
end
|
|
11
11
|
gem.add_runtime_dependency 'carrot-top', '~> 0.0.7'
|
|
12
12
|
gem.add_runtime_dependency 'multi_json', '~> 1.15'
|
|
13
|
-
gem.add_runtime_dependency 'activesupport', '>= 4.2', '
|
|
13
|
+
gem.add_runtime_dependency 'activesupport', '>= 4.2', '<= 8'
|
|
14
14
|
|
|
15
15
|
gem.name = 'hutch'
|
|
16
16
|
gem.summary = 'Opinionated asynchronous inter-service communication using RabbitMQ'
|
|
17
17
|
gem.description = 'Hutch is a Ruby library for enabling asynchronous inter-service communication using RabbitMQ'
|
|
18
18
|
gem.version = Hutch::VERSION.dup
|
|
19
|
-
gem.required_ruby_version = '>= 2.
|
|
19
|
+
gem.required_ruby_version = '>= 2.6'
|
|
20
20
|
gem.authors = ['Harry Marr', 'Michael Klishin']
|
|
21
21
|
gem.homepage = 'https://github.com/ruby-amqp/hutch'
|
|
22
22
|
gem.require_paths = ['lib']
|
data/lib/hutch/broker.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'active_support/core_ext/object/blank'
|
|
2
2
|
|
|
3
3
|
require 'carrot-top'
|
|
4
|
+
require 'ostruct'
|
|
4
5
|
require 'hutch/logging'
|
|
5
6
|
require 'hutch/exceptions'
|
|
6
7
|
require 'hutch/publisher'
|
|
@@ -174,8 +175,8 @@ module Hutch
|
|
|
174
175
|
def queue(name, options = {})
|
|
175
176
|
with_bunny_precondition_handler('queue') do
|
|
176
177
|
namespace = @config[:namespace].to_s.downcase.gsub(/[^-_:\.\w]/, "")
|
|
177
|
-
|
|
178
|
-
channel.queue(
|
|
178
|
+
queue_name = namespace.present? ? "#{namespace}:#{name}" : name
|
|
179
|
+
channel.queue(queue_name, **options)
|
|
179
180
|
end
|
|
180
181
|
end
|
|
181
182
|
|
|
@@ -287,6 +288,7 @@ module Hutch
|
|
|
287
288
|
params[:host] = @config[:mq_host]
|
|
288
289
|
params[:port] = @config[:mq_port]
|
|
289
290
|
params[:vhost] = @config[:mq_vhost].presence || Hutch::Adapter::DEFAULT_VHOST
|
|
291
|
+
params[:auth_mechanism] = @config[:mq_auth_mechanism]
|
|
290
292
|
params[:username] = @config[:mq_username]
|
|
291
293
|
params[:password] = @config[:mq_password]
|
|
292
294
|
params[:tls] = @config[:mq_tls]
|
|
@@ -297,6 +299,8 @@ module Hutch
|
|
|
297
299
|
params[:tls_ca_certificates] = @config[:mq_tls_ca_certificates]
|
|
298
300
|
end
|
|
299
301
|
params[:heartbeat] = @config[:heartbeat]
|
|
302
|
+
params[:client_properties] = @config[:mq_client_properties]
|
|
303
|
+
params[:connection_name] = @config[:connection_name]
|
|
300
304
|
params[:connection_timeout] = @config[:connection_timeout]
|
|
301
305
|
params[:read_timeout] = @config[:read_timeout]
|
|
302
306
|
params[:write_timeout] = @config[:write_timeout]
|
data/lib/hutch/cli.rb
CHANGED
|
@@ -65,7 +65,7 @@ module Hutch
|
|
|
65
65
|
return false
|
|
66
66
|
ensure
|
|
67
67
|
# Clean up load path
|
|
68
|
-
$LOAD_PATH.
|
|
68
|
+
$LOAD_PATH.delete('.')
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
71
|
end
|
|
@@ -234,7 +234,7 @@ module Hutch
|
|
|
234
234
|
end
|
|
235
235
|
|
|
236
236
|
def abort_without_file(file, file_description, &block)
|
|
237
|
-
abort_with_message("#{file_description} '#{file}' not found") unless File.
|
|
237
|
+
abort_with_message("#{file_description} '#{file}' not found") unless File.exist?(file)
|
|
238
238
|
|
|
239
239
|
yield
|
|
240
240
|
end
|
data/lib/hutch/config.rb
CHANGED
|
@@ -63,6 +63,9 @@ module Hutch
|
|
|
63
63
|
# RabbitMQ password
|
|
64
64
|
string_setting :mq_password, 'guest'
|
|
65
65
|
|
|
66
|
+
# RabbitMQ Auth Mechanism
|
|
67
|
+
string_setting :mq_auth_mechanism, 'PLAIN'
|
|
68
|
+
|
|
66
69
|
# RabbitMQ URI (takes precedence over MQ username, password, host, port and vhost settings)
|
|
67
70
|
string_setting :uri, nil
|
|
68
71
|
|
|
@@ -83,6 +86,9 @@ module Hutch
|
|
|
83
86
|
# Default: `0`, no limit. See Bunny and RabbitMQ documentation.
|
|
84
87
|
number_setting :channel_prefetch, 0
|
|
85
88
|
|
|
89
|
+
# [Client-Provided Connection Name](https://www.rabbitmq.com/docs/connections#client-provided-names)
|
|
90
|
+
string_setting :connection_name, nil
|
|
91
|
+
|
|
86
92
|
# Bunny's socket open timeout
|
|
87
93
|
number_setting :connection_timeout, 11
|
|
88
94
|
|
|
@@ -168,6 +174,7 @@ module Hutch
|
|
|
168
174
|
# @return [Hash]
|
|
169
175
|
def self.default_config
|
|
170
176
|
@settings_defaults.merge({
|
|
177
|
+
mq_client_properties: {},
|
|
171
178
|
mq_exchange_options: {},
|
|
172
179
|
mq_tls_cert: nil,
|
|
173
180
|
mq_tls_key: nil,
|
|
@@ -222,7 +229,12 @@ module Hutch
|
|
|
222
229
|
end
|
|
223
230
|
|
|
224
231
|
def self.to_bool(value)
|
|
225
|
-
|
|
232
|
+
case value
|
|
233
|
+
when nil, false, '', /^(false|f|no|n|0)$/i
|
|
234
|
+
false
|
|
235
|
+
else
|
|
236
|
+
true
|
|
237
|
+
end
|
|
226
238
|
end
|
|
227
239
|
|
|
228
240
|
def self.is_num(attr)
|
data/lib/hutch/consumer.rb
CHANGED
|
@@ -13,13 +13,19 @@ module Hutch
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def reject!
|
|
16
|
+
@message_rejected = true
|
|
16
17
|
broker.reject(delivery_info.delivery_tag)
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def requeue!
|
|
21
|
+
@message_rejected = true
|
|
20
22
|
broker.requeue(delivery_info.delivery_tag)
|
|
21
23
|
end
|
|
22
24
|
|
|
25
|
+
def message_rejected?
|
|
26
|
+
!!@message_rejected
|
|
27
|
+
end
|
|
28
|
+
|
|
23
29
|
def logger
|
|
24
30
|
Hutch::Logging.logger
|
|
25
31
|
end
|
|
@@ -11,7 +11,7 @@ module Hutch
|
|
|
11
11
|
logger.error "#{prefix} Logging event to Sentry"
|
|
12
12
|
logger.error "#{prefix} #{ex.class} - #{ex.message}"
|
|
13
13
|
::Sentry.configure_scope do |scope|
|
|
14
|
-
scope.set_context("payload", payload)
|
|
14
|
+
scope.set_context("payload", JSON.parse(payload))
|
|
15
15
|
end
|
|
16
16
|
::Sentry.capture_exception(ex)
|
|
17
17
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'ddtrace'
|
|
2
|
+
require 'ddtrace/auto_instrument'
|
|
2
3
|
|
|
3
4
|
module Hutch
|
|
4
5
|
module Tracers
|
|
@@ -8,7 +9,7 @@ module Hutch
|
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
def handle(message)
|
|
11
|
-
::Datadog.
|
|
12
|
+
::Datadog::Tracing.trace(@klass.class.name, continue_from: nil, service: 'hutch', type: 'rabbitmq') do
|
|
12
13
|
@klass.process(message)
|
|
13
14
|
end
|
|
14
15
|
end
|
data/lib/hutch/version.rb
CHANGED
data/lib/hutch/worker.rb
CHANGED
|
@@ -71,10 +71,10 @@ module Hutch
|
|
|
71
71
|
message = Message.new(delivery_info, properties, payload, serializer)
|
|
72
72
|
consumer_instance = consumer.new.tap { |c| c.broker, c.delivery_info = @broker, delivery_info }
|
|
73
73
|
with_tracing(consumer_instance).handle(message)
|
|
74
|
-
@broker.ack(delivery_info.delivery_tag)
|
|
74
|
+
@broker.ack(delivery_info.delivery_tag) unless consumer_instance.message_rejected?
|
|
75
75
|
rescue => ex
|
|
76
76
|
acknowledge_error(delivery_info, properties, @broker, ex)
|
|
77
|
-
handle_error(properties, payload, consumer, ex)
|
|
77
|
+
handle_error(properties, payload, consumer, ex, delivery_info)
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
def with_tracing(klass)
|
|
@@ -83,7 +83,7 @@ module Hutch
|
|
|
83
83
|
|
|
84
84
|
def handle_error(*args)
|
|
85
85
|
Hutch::Config[:error_handlers].each do |backend|
|
|
86
|
-
backend.handle
|
|
86
|
+
backend.handle *args.first(backend.method(:handle).arity)
|
|
87
87
|
end
|
|
88
88
|
end
|
|
89
89
|
|
data/spec/hutch/broker_spec.rb
CHANGED
|
@@ -119,7 +119,7 @@ describe Hutch::Broker do
|
|
|
119
119
|
|
|
120
120
|
it 'utilises TLS' do
|
|
121
121
|
expect(Hutch::Adapter).to receive(:new).with(
|
|
122
|
-
hash_including(tls: true
|
|
122
|
+
hash_including(tls: true)
|
|
123
123
|
).and_return(instance_double('Hutch::Adapter', start: nil))
|
|
124
124
|
|
|
125
125
|
broker.open_connection
|
|
@@ -245,9 +245,9 @@ describe Hutch::Broker do
|
|
|
245
245
|
context 'when given invalid details' do
|
|
246
246
|
before { config[:mq_api_host] = 'notarealhost' }
|
|
247
247
|
after { broker.disconnect }
|
|
248
|
-
let(:set_up_api_connection) {
|
|
248
|
+
let(:set_up_api_connection) { broker.set_up_api_connection }
|
|
249
249
|
|
|
250
|
-
specify { expect
|
|
250
|
+
specify { expect { broker.set_up_api_connection }.to raise_error(StandardError) }
|
|
251
251
|
end
|
|
252
252
|
end
|
|
253
253
|
|
|
@@ -262,7 +262,7 @@ describe Hutch::Broker do
|
|
|
262
262
|
args.first == ''
|
|
263
263
|
args.last == arguments
|
|
264
264
|
end
|
|
265
|
-
broker.queue('test', arguments: arguments)
|
|
265
|
+
broker.queue('test'.freeze, arguments: arguments)
|
|
266
266
|
end
|
|
267
267
|
end
|
|
268
268
|
|
data/spec/hutch/config_spec.rb
CHANGED
|
@@ -31,12 +31,10 @@ describe Hutch::Config do
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
context 'for invalid attributes' do
|
|
34
|
-
let(:invalid_get)
|
|
35
|
-
-> { Hutch::Config.get(:invalid_attr) }
|
|
36
|
-
end
|
|
34
|
+
let(:invalid_get) { Hutch::Config.get(:invalid_attr) }
|
|
37
35
|
|
|
38
36
|
specify do
|
|
39
|
-
expect
|
|
37
|
+
expect { invalid_get }.to raise_error Hutch::UnknownAttributeError
|
|
40
38
|
end
|
|
41
39
|
end
|
|
42
40
|
end
|
|
@@ -65,14 +63,52 @@ describe Hutch::Config do
|
|
|
65
63
|
end
|
|
66
64
|
|
|
67
65
|
context 'boolean attributes' do
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
context 'from non-empty string' do
|
|
67
|
+
before { Hutch::Config.set(:autoload_rails, new_value) }
|
|
68
|
+
subject(:value) { Hutch::Config.user_config[:autoload_rails] }
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
let(:new_value) { "t" }
|
|
72
71
|
|
|
73
72
|
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
specify 'casts values to booleans' do
|
|
74
|
+
expect(value).to eq true
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context 'from empty string' do
|
|
79
|
+
before { Hutch::Config.set(:autoload_rails, new_value) }
|
|
80
|
+
subject(:value) { Hutch::Config.user_config[:autoload_rails] }
|
|
81
|
+
|
|
82
|
+
let(:new_value) { "" }
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
specify 'casts values to booleans' do
|
|
86
|
+
expect(value).to eq false
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context 'from boolean' do
|
|
91
|
+
before { Hutch::Config.set(:autoload_rails, new_value) }
|
|
92
|
+
subject(:value) { Hutch::Config.user_config[:autoload_rails] }
|
|
93
|
+
|
|
94
|
+
let(:new_value) { true }
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
specify 'casts values to booleans' do
|
|
98
|
+
expect(value).to eq true
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context 'from nil' do
|
|
103
|
+
before { Hutch::Config.set(:autoload_rails, new_value) }
|
|
104
|
+
subject(:value) { Hutch::Config.user_config[:autoload_rails] }
|
|
105
|
+
|
|
106
|
+
let(:new_value) { nil }
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
specify 'casts values to booleans' do
|
|
110
|
+
expect(value).to eq false
|
|
111
|
+
end
|
|
76
112
|
end
|
|
77
113
|
end
|
|
78
114
|
|
|
@@ -90,12 +126,10 @@ describe Hutch::Config do
|
|
|
90
126
|
end
|
|
91
127
|
|
|
92
128
|
context 'for invalid attributes' do
|
|
93
|
-
let(:invalid_set)
|
|
94
|
-
-> { Hutch::Config.set(:invalid_attr, new_value) }
|
|
95
|
-
end
|
|
129
|
+
let(:invalid_set) { Hutch::Config.set(:invalid_attr, new_value) }
|
|
96
130
|
|
|
97
131
|
specify do
|
|
98
|
-
expect
|
|
132
|
+
expect { invalid_set }.to raise_error Hutch::UnknownAttributeError
|
|
99
133
|
end
|
|
100
134
|
end
|
|
101
135
|
end
|
|
@@ -109,8 +143,8 @@ describe Hutch::Config do
|
|
|
109
143
|
end
|
|
110
144
|
|
|
111
145
|
context 'for an invalid attribute' do
|
|
112
|
-
let(:invalid_getter) {
|
|
113
|
-
specify { expect
|
|
146
|
+
let(:invalid_getter) { Hutch::Config.invalid_attr }
|
|
147
|
+
specify { expect { invalid_getter }.to raise_error NoMethodError }
|
|
114
148
|
end
|
|
115
149
|
|
|
116
150
|
context 'for an ENV-overriden value attribute' do
|
|
@@ -147,8 +181,8 @@ describe Hutch::Config do
|
|
|
147
181
|
end
|
|
148
182
|
|
|
149
183
|
context 'for an invalid attribute' do
|
|
150
|
-
let(:invalid_setter) {
|
|
151
|
-
specify { expect
|
|
184
|
+
let(:invalid_setter) { Hutch::Config.invalid_attr = new_value }
|
|
185
|
+
specify { expect { invalid_setter }.to raise_error NoMethodError }
|
|
152
186
|
end
|
|
153
187
|
end
|
|
154
188
|
|
|
@@ -15,7 +15,7 @@ describe Hutch::ErrorHandlers::SentryRaven do
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
it "logs the error to Sentry" do
|
|
18
|
-
expect(Raven).to receive(:capture_exception).with(error, extra: { payload: payload })
|
|
18
|
+
expect(Raven).to receive(:capture_exception).with(error, {extra: { payload: payload }})
|
|
19
19
|
error_handler.handle(properties, payload, double, error)
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -3,6 +3,14 @@ require 'spec_helper'
|
|
|
3
3
|
describe Hutch::ErrorHandlers::Sentry do
|
|
4
4
|
let(:error_handler) { Hutch::ErrorHandlers::Sentry.new }
|
|
5
5
|
|
|
6
|
+
before do
|
|
7
|
+
Sentry.init do
|
|
8
|
+
# initialize Sentry so that the integration acutally works
|
|
9
|
+
# otherwise, all its methods are going to return early
|
|
10
|
+
# so it will be impossible to check if it actually works
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
6
14
|
describe '#handle' do
|
|
7
15
|
let(:properties) { OpenStruct.new(message_id: "1") }
|
|
8
16
|
let(:payload) { "{}" }
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
RSpec.describe Hutch::Tracers::Datadog do
|
|
4
|
+
::Datadog.logger.level = Logger::FATAL # suppress logging
|
|
5
|
+
|
|
4
6
|
describe "#handle" do
|
|
5
7
|
subject(:handle) { tracer.handle(message) }
|
|
6
8
|
|
|
@@ -25,14 +27,14 @@ RSpec.describe Hutch::Tracers::Datadog do
|
|
|
25
27
|
let(:message) { double(:message) }
|
|
26
28
|
|
|
27
29
|
before do
|
|
28
|
-
allow(Datadog
|
|
30
|
+
allow(::Datadog::Tracing).to receive(:trace).and_call_original
|
|
29
31
|
end
|
|
30
32
|
|
|
31
33
|
it 'uses Datadog tracer' do
|
|
32
34
|
handle
|
|
33
35
|
|
|
34
|
-
expect(Datadog
|
|
35
|
-
hash_including(service: 'hutch',
|
|
36
|
+
expect(::Datadog::Tracing).to have_received(:trace).with('ClassName',
|
|
37
|
+
hash_including(service: 'hutch', type: 'rabbitmq'))
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
it 'processes the message' do
|
data/spec/hutch/worker_spec.rb
CHANGED
|
@@ -69,27 +69,32 @@ describe Hutch::Worker do
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
describe '#handle_message' do
|
|
72
|
+
subject { worker.handle_message(consumer, delivery_info, properties, payload) }
|
|
72
73
|
let(:payload) { '{}' }
|
|
73
74
|
let(:consumer_instance) { double('Consumer instance') }
|
|
74
75
|
let(:delivery_info) { double('Delivery Info', routing_key: '',
|
|
75
76
|
delivery_tag: 'dt') }
|
|
76
77
|
let(:properties) { double('Properties', message_id: nil, content_type: "application/json") }
|
|
78
|
+
let(:log) { StringIO.new }
|
|
77
79
|
before { allow(consumer).to receive_messages(new: consumer_instance) }
|
|
78
80
|
before { allow(broker).to receive(:ack) }
|
|
79
81
|
before { allow(broker).to receive(:nack) }
|
|
80
82
|
before { allow(consumer_instance).to receive(:broker=) }
|
|
81
83
|
before { allow(consumer_instance).to receive(:delivery_info=) }
|
|
84
|
+
before { allow(Hutch::Logging).to receive(:logger).and_return(Logger.new(log)) }
|
|
82
85
|
|
|
83
86
|
it 'passes the message to the consumer' do
|
|
84
87
|
expect(consumer_instance).to receive(:process).
|
|
85
88
|
with(an_instance_of(Hutch::Message))
|
|
86
|
-
|
|
89
|
+
expect(consumer_instance).to receive(:message_rejected?).and_return(false)
|
|
90
|
+
subject
|
|
87
91
|
end
|
|
88
92
|
|
|
89
93
|
it 'acknowledges the message' do
|
|
90
94
|
allow(consumer_instance).to receive(:process)
|
|
91
95
|
expect(broker).to receive(:ack).with(delivery_info.delivery_tag)
|
|
92
|
-
|
|
96
|
+
expect(consumer_instance).to receive(:message_rejected?).and_return(false)
|
|
97
|
+
subject
|
|
93
98
|
end
|
|
94
99
|
|
|
95
100
|
context 'when the consumer fails and a requeue is configured' do
|
|
@@ -106,40 +111,79 @@ describe Hutch::Worker do
|
|
|
106
111
|
expect(broker).to_not receive(:nack)
|
|
107
112
|
expect(broker).to receive(:requeue)
|
|
108
113
|
|
|
109
|
-
|
|
114
|
+
subject
|
|
110
115
|
end
|
|
111
116
|
end
|
|
112
117
|
|
|
113
118
|
|
|
114
119
|
context 'when the consumer raises an exception' do
|
|
120
|
+
let(:expected_log) { /ERROR .+ error in consumer .+ RuntimeError .+ backtrace:/m }
|
|
115
121
|
before { allow(consumer_instance).to receive(:process).and_raise('a consumer error') }
|
|
116
122
|
|
|
117
123
|
it 'logs the error' do
|
|
118
|
-
|
|
119
|
-
expect(backend).to receive(:handle)
|
|
120
|
-
end
|
|
121
|
-
worker.handle_message(consumer, delivery_info, properties, payload)
|
|
124
|
+
expect { subject }.to change { log.tap(&:rewind).read }.from("").to(expected_log)
|
|
122
125
|
end
|
|
123
126
|
|
|
124
127
|
it 'rejects the message' do
|
|
125
128
|
expect(broker).to receive(:nack).with(delivery_info.delivery_tag)
|
|
126
|
-
|
|
129
|
+
subject
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
context 'when a custom error handler supports delivery info' do
|
|
133
|
+
let(:error_handler) do
|
|
134
|
+
Class.new(Hutch::ErrorHandlers::Base) do
|
|
135
|
+
def handle(_properties, _payload, _consumer, _ex, delivery_info)
|
|
136
|
+
raise unless delivery_info.delivery_tag == 'dt'
|
|
137
|
+
puts 'handled!'
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
around do |example|
|
|
143
|
+
original = Hutch::Config[:error_handlers]
|
|
144
|
+
Hutch::Config[:error_handlers] = [error_handler.new]
|
|
145
|
+
example.run
|
|
146
|
+
Hutch::Config[:error_handlers] = original
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'calls the custom handler with delivery info' do
|
|
150
|
+
expect { subject }.to output("handled!\n").to_stdout
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context 'when a custom error handler does not support delivery info' do
|
|
155
|
+
let(:error_handler) do
|
|
156
|
+
Class.new(Hutch::ErrorHandlers::Base) do
|
|
157
|
+
def handle(_properties, _payload, _consumer, _ex)
|
|
158
|
+
puts 'handled!'
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
around do |example|
|
|
164
|
+
original = Hutch::Config[:error_handlers]
|
|
165
|
+
Hutch::Config[:error_handlers] = [error_handler.new]
|
|
166
|
+
example.run
|
|
167
|
+
Hutch::Config[:error_handlers] = original
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it 'calls the custom handler with delivery info' do
|
|
171
|
+
expect { subject }.to output("handled!\n").to_stdout
|
|
172
|
+
end
|
|
127
173
|
end
|
|
128
174
|
end
|
|
129
175
|
|
|
130
176
|
context "when the payload is not valid json" do
|
|
131
177
|
let(:payload) { "Not Valid JSON" }
|
|
178
|
+
let(:expected_log) { /ERROR .+ error in consumer .+ MultiJson::ParseError .+ backtrace:/m }
|
|
132
179
|
|
|
133
180
|
it 'logs the error' do
|
|
134
|
-
|
|
135
|
-
expect(backend).to receive(:handle)
|
|
136
|
-
end
|
|
137
|
-
worker.handle_message(consumer, delivery_info, properties, payload)
|
|
181
|
+
expect { subject }.to change { log.tap(&:rewind).read }.from("").to(expected_log)
|
|
138
182
|
end
|
|
139
183
|
|
|
140
184
|
it 'rejects the message' do
|
|
141
185
|
expect(broker).to receive(:nack).with(delivery_info.delivery_tag)
|
|
142
|
-
|
|
186
|
+
subject
|
|
143
187
|
end
|
|
144
188
|
end
|
|
145
189
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hutch
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Harry Marr
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2024-11-11 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: bunny
|
|
@@ -17,7 +17,7 @@ dependencies:
|
|
|
17
17
|
requirements:
|
|
18
18
|
- - ">="
|
|
19
19
|
- !ruby/object:Gem::Version
|
|
20
|
-
version: '2.
|
|
20
|
+
version: '2.23'
|
|
21
21
|
- - "<"
|
|
22
22
|
- !ruby/object:Gem::Version
|
|
23
23
|
version: '3.0'
|
|
@@ -27,7 +27,7 @@ dependencies:
|
|
|
27
27
|
requirements:
|
|
28
28
|
- - ">="
|
|
29
29
|
- !ruby/object:Gem::Version
|
|
30
|
-
version: '2.
|
|
30
|
+
version: '2.23'
|
|
31
31
|
- - "<"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
33
|
version: '3.0'
|
|
@@ -66,7 +66,7 @@ dependencies:
|
|
|
66
66
|
- - ">="
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '4.2'
|
|
69
|
-
- - "
|
|
69
|
+
- - "<="
|
|
70
70
|
- !ruby/object:Gem::Version
|
|
71
71
|
version: '8'
|
|
72
72
|
type: :runtime
|
|
@@ -76,7 +76,7 @@ dependencies:
|
|
|
76
76
|
- - ">="
|
|
77
77
|
- !ruby/object:Gem::Version
|
|
78
78
|
version: '4.2'
|
|
79
|
-
- - "
|
|
79
|
+
- - "<="
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
81
|
version: '8'
|
|
82
82
|
description: Hutch is a Ruby library for enabling asynchronous inter-service communication
|
|
@@ -178,14 +178,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
178
178
|
requirements:
|
|
179
179
|
- - ">="
|
|
180
180
|
- !ruby/object:Gem::Version
|
|
181
|
-
version: '2.
|
|
181
|
+
version: '2.6'
|
|
182
182
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
183
|
requirements:
|
|
184
184
|
- - ">="
|
|
185
185
|
- !ruby/object:Gem::Version
|
|
186
186
|
version: '0'
|
|
187
187
|
requirements: []
|
|
188
|
-
rubygems_version: 3.
|
|
188
|
+
rubygems_version: 3.5.22
|
|
189
189
|
signing_key:
|
|
190
190
|
specification_version: 4
|
|
191
191
|
summary: Opinionated asynchronous inter-service communication using RabbitMQ
|