shivam 0.0.0-java
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 +7 -0
- data/.github/workflows/test.yml +57 -0
- data/.gitignore +10 -0
- data/.rspec +1 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +899 -0
- data/Gemfile +35 -0
- data/Guardfile +14 -0
- data/LICENSE +23 -0
- data/README.md +679 -0
- data/Rakefile +21 -0
- data/bin/ci/before_build.sh +20 -0
- data/bin/ci/before_build_docker.sh +20 -0
- data/bin/ci/install_on_debian.sh +46 -0
- data/bin/hutch +8 -0
- data/examples/consumer.rb +13 -0
- data/examples/producer.rb +10 -0
- data/hutch.gemspec +27 -0
- data/lib/hutch/acknowledgements/base.rb +16 -0
- data/lib/hutch/acknowledgements/nack_on_all_failures.rb +19 -0
- data/lib/hutch/adapter.rb +11 -0
- data/lib/hutch/adapters/bunny.rb +37 -0
- data/lib/hutch/adapters/march_hare.rb +41 -0
- data/lib/hutch/broker.rb +384 -0
- data/lib/hutch/cli.rb +246 -0
- data/lib/hutch/config.rb +305 -0
- data/lib/hutch/consumer.rb +125 -0
- data/lib/hutch/error_handlers/airbrake.rb +54 -0
- data/lib/hutch/error_handlers/base.rb +15 -0
- data/lib/hutch/error_handlers/bugsnag.rb +30 -0
- data/lib/hutch/error_handlers/honeybadger.rb +43 -0
- data/lib/hutch/error_handlers/logger.rb +22 -0
- data/lib/hutch/error_handlers/rollbar.rb +28 -0
- data/lib/hutch/error_handlers/sentry.rb +26 -0
- data/lib/hutch/error_handlers/sentry_raven.rb +31 -0
- data/lib/hutch/error_handlers.rb +11 -0
- data/lib/hutch/exceptions.rb +14 -0
- data/lib/hutch/logging.rb +32 -0
- data/lib/hutch/message.rb +31 -0
- data/lib/hutch/publisher.rb +75 -0
- data/lib/hutch/serializers/identity.rb +19 -0
- data/lib/hutch/serializers/json.rb +22 -0
- data/lib/hutch/tracers/datadog.rb +18 -0
- data/lib/hutch/tracers/newrelic.rb +19 -0
- data/lib/hutch/tracers/null_tracer.rb +15 -0
- data/lib/hutch/tracers.rb +7 -0
- data/lib/hutch/version.rb +3 -0
- data/lib/hutch/waiter.rb +104 -0
- data/lib/hutch/worker.rb +145 -0
- data/lib/hutch.rb +69 -0
- data/lib/yard-settings/handler.rb +38 -0
- data/lib/yard-settings/yard-settings.rb +2 -0
- data/spec/hutch/broker_spec.rb +462 -0
- data/spec/hutch/cli_spec.rb +93 -0
- data/spec/hutch/config_spec.rb +259 -0
- data/spec/hutch/consumer_spec.rb +208 -0
- data/spec/hutch/error_handlers/airbrake_spec.rb +49 -0
- data/spec/hutch/error_handlers/bugsnag_spec.rb +55 -0
- data/spec/hutch/error_handlers/honeybadger_spec.rb +58 -0
- data/spec/hutch/error_handlers/logger_spec.rb +28 -0
- data/spec/hutch/error_handlers/rollbar_spec.rb +45 -0
- data/spec/hutch/error_handlers/sentry_raven_spec.rb +37 -0
- data/spec/hutch/error_handlers/sentry_spec.rb +47 -0
- data/spec/hutch/logger_spec.rb +34 -0
- data/spec/hutch/message_spec.rb +38 -0
- data/spec/hutch/serializers/json_spec.rb +17 -0
- data/spec/hutch/tracers/datadog_spec.rb +44 -0
- data/spec/hutch/waiter_spec.rb +51 -0
- data/spec/hutch/worker_spec.rb +184 -0
- data/spec/hutch_spec.rb +87 -0
- data/spec/spec_helper.rb +42 -0
- data/templates/default/class/html/settings.erb +0 -0
- data/templates/default/class/setup.rb +4 -0
- data/templates/default/fulldoc/html/css/hutch.css +13 -0
- data/templates/default/layout/html/setup.rb +7 -0
- data/templates/default/method_details/html/settings.erb +5 -0
- data/templates/default/method_details/setup.rb +4 -0
- data/templates/default/method_details/text/settings.erb +0 -0
- data/templates/default/module/html/settings.erb +40 -0
- data/templates/default/module/setup.rb +4 -0
- metadata +205 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hutch::ErrorHandlers::SentryRaven do
|
4
|
+
let(:error_handler) { Hutch::ErrorHandlers::SentryRaven.new }
|
5
|
+
|
6
|
+
describe '#handle' do
|
7
|
+
let(:properties) { OpenStruct.new(message_id: "1") }
|
8
|
+
let(:payload) { "{}" }
|
9
|
+
let(:error) do
|
10
|
+
begin
|
11
|
+
raise "Stuff went wrong"
|
12
|
+
rescue RuntimeError => err
|
13
|
+
err
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "logs the error to Sentry" do
|
18
|
+
expect(Raven).to receive(:capture_exception).with(error, {extra: { payload: payload }})
|
19
|
+
error_handler.handle(properties, payload, double, error)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#handle_setup_exception' do
|
24
|
+
let(:error) do
|
25
|
+
begin
|
26
|
+
raise "Stuff went wrong during setup"
|
27
|
+
rescue RuntimeError => err
|
28
|
+
err
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "logs the error to Sentry" do
|
33
|
+
expect(Raven).to receive(:capture_exception).with(error)
|
34
|
+
error_handler.handle_setup_exception(error)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hutch::ErrorHandlers::Sentry do
|
4
|
+
let(:error_handler) { Hutch::ErrorHandlers::Sentry.new }
|
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
|
+
|
14
|
+
describe '#handle' do
|
15
|
+
let(:properties) { OpenStruct.new(message_id: "1") }
|
16
|
+
let(:payload) { "{}" }
|
17
|
+
let(:error) do
|
18
|
+
begin
|
19
|
+
raise "Stuff went wrong"
|
20
|
+
rescue RuntimeError => err
|
21
|
+
err
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "logs the error to Sentry" do
|
26
|
+
expect(::Sentry).to receive(:capture_exception).with(error).and_call_original
|
27
|
+
|
28
|
+
error_handler.handle(properties, payload, double, error)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#handle_setup_exception' do
|
33
|
+
let(:error) do
|
34
|
+
begin
|
35
|
+
raise "Stuff went wrong during setup"
|
36
|
+
rescue RuntimeError => err
|
37
|
+
err
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "logs the error to Sentry" do
|
42
|
+
expect(::Sentry).to receive(:capture_exception).with(error).and_call_original
|
43
|
+
|
44
|
+
error_handler.handle_setup_exception(error)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hutch::Logging do
|
4
|
+
let(:dummy_object) do
|
5
|
+
class DummyObject
|
6
|
+
include described_class
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#logger' do
|
11
|
+
around do |example|
|
12
|
+
old_logger = described_class.logger
|
13
|
+
described_class.setup_logger
|
14
|
+
example.run
|
15
|
+
described_class.logger = old_logger
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with the default logger' do
|
19
|
+
subject { described_class.logger }
|
20
|
+
|
21
|
+
it { is_expected.to be_instance_of(Logger) }
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'with a custom logger' do
|
25
|
+
let(:dummy_logger) { double("Dummy logger") }
|
26
|
+
|
27
|
+
it "users the custom logger" do
|
28
|
+
described_class.logger = dummy_logger
|
29
|
+
expect(described_class.logger).to eq(dummy_logger)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'hutch/message'
|
2
|
+
|
3
|
+
describe Hutch::Message do
|
4
|
+
let(:delivery_info) { double('Delivery Info') }
|
5
|
+
let(:props) { double('Properties', content_type: "application/json") }
|
6
|
+
let(:body) {{ foo: 'bar' }.with_indifferent_access}
|
7
|
+
let(:json_body) { MultiJson.dump(body) }
|
8
|
+
subject(:message) { Hutch::Message.new(delivery_info, props, json_body, Hutch::Config[:serializer]) }
|
9
|
+
|
10
|
+
describe '#body' do
|
11
|
+
subject { super().body }
|
12
|
+
it { is_expected.to eq(body) }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '[]' do
|
16
|
+
subject { message[:foo] }
|
17
|
+
it { is_expected.to eq('bar') }
|
18
|
+
end
|
19
|
+
|
20
|
+
[:message_id, :timestamp].each do |method|
|
21
|
+
describe method.to_s do
|
22
|
+
it 'delegates to @properties' do
|
23
|
+
expect(props).to receive(method)
|
24
|
+
message.send(method)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
[:routing_key, :exchange].each do |method|
|
30
|
+
describe method.to_s do
|
31
|
+
it 'delegates to @delivery_info' do
|
32
|
+
expect(delivery_info).to receive(method)
|
33
|
+
message.send(method)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hutch::Serializers::JSON do
|
4
|
+
let(:subject) { described_class }
|
5
|
+
|
6
|
+
it "encode/decode" do
|
7
|
+
payload = { a: 1, b: 2 }
|
8
|
+
encoded = subject.encode(payload)
|
9
|
+
decoded = subject.decode(encoded)
|
10
|
+
|
11
|
+
expect(encoded).to eq "{\"a\":1,\"b\":2}"
|
12
|
+
expect(decoded).to eq("a" => 1, "b" => 2)
|
13
|
+
expect(decoded[:a]).to eq 1
|
14
|
+
expect(decoded[:b]).to eq 2
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Hutch::Tracers::Datadog do
|
4
|
+
describe "#handle" do
|
5
|
+
subject(:handle) { tracer.handle(message) }
|
6
|
+
|
7
|
+
let(:tracer) { described_class.new(klass) }
|
8
|
+
let(:klass) do
|
9
|
+
Class.new do
|
10
|
+
attr_reader :message
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@message = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def class
|
17
|
+
OpenStruct.new(name: 'ClassName')
|
18
|
+
end
|
19
|
+
|
20
|
+
def process(message)
|
21
|
+
@message = message
|
22
|
+
end
|
23
|
+
end.new
|
24
|
+
end
|
25
|
+
let(:message) { double(:message) }
|
26
|
+
|
27
|
+
before do
|
28
|
+
allow(::Datadog::Tracing).to receive(:trace).and_call_original
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'uses Datadog tracer' do
|
32
|
+
handle
|
33
|
+
|
34
|
+
expect(::Datadog::Tracing).to have_received(:trace).with('ClassName',
|
35
|
+
hash_including(service: 'hutch', type: 'rabbitmq'))
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'processes the message' do
|
39
|
+
expect {
|
40
|
+
handle
|
41
|
+
}.to change { klass.message }.from(nil).to(message)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'hutch/waiter'
|
2
|
+
|
3
|
+
RSpec.describe Hutch::Waiter do
|
4
|
+
describe '.wait_until_signaled' do
|
5
|
+
let(:pid) { Process.pid }
|
6
|
+
def start_kill_thread(signal)
|
7
|
+
Thread.new do
|
8
|
+
# sleep allows the worker time to set up the signal handling
|
9
|
+
# before the kill signal is sent.
|
10
|
+
sleep 0.001
|
11
|
+
Process.kill signal, pid
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'a QUIT signal is received', if: RSpec::Support::Ruby.mri? do
|
16
|
+
it 'logs that hutch is stopping' do
|
17
|
+
expect(Hutch::Logging.logger).to receive(:info)
|
18
|
+
.with('caught SIGQUIT, stopping hutch...')
|
19
|
+
|
20
|
+
start_kill_thread('QUIT')
|
21
|
+
described_class.wait_until_signaled
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'a TERM signal is received', if: !defined?(JRUBY_VERSION) do
|
26
|
+
it 'logs that hutch is stopping' do
|
27
|
+
expect(Hutch::Logging.logger).to receive(:info)
|
28
|
+
.with('caught SIGTERM, stopping hutch...')
|
29
|
+
|
30
|
+
start_kill_thread('TERM')
|
31
|
+
described_class.wait_until_signaled
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'a INT signal is received', if: !defined?(JRUBY_VERSION) do
|
36
|
+
it 'logs that hutch is stopping' do
|
37
|
+
expect(Hutch::Logging.logger).to receive(:info)
|
38
|
+
.with('caught SIGINT, stopping hutch...')
|
39
|
+
|
40
|
+
start_kill_thread('INT')
|
41
|
+
described_class.wait_until_signaled
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe described_class::SHUTDOWN_SIGNALS do
|
47
|
+
it 'includes only things in Signal.list.keys' do
|
48
|
+
expect(described_class).to eq(described_class & Signal.list.keys)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'hutch/worker'
|
3
|
+
|
4
|
+
describe Hutch::Worker do
|
5
|
+
let(:consumer) { double('Consumer', routing_keys: %w( a b c ),
|
6
|
+
get_queue_name: 'consumer', get_arguments: {},
|
7
|
+
get_options: {}, get_serializer: nil) }
|
8
|
+
let(:consumers) { [consumer, double('Consumer')] }
|
9
|
+
let(:broker) { Hutch::Broker.new }
|
10
|
+
let(:setup_procs) { Array.new(2) { Proc.new {} } }
|
11
|
+
subject(:worker) { Hutch::Worker.new(broker, consumers, setup_procs) }
|
12
|
+
|
13
|
+
describe ".#run" do
|
14
|
+
it "calls each setup proc" do
|
15
|
+
setup_procs.each { |prc| expect(prc).to receive(:call) }
|
16
|
+
allow(worker).to receive(:setup_queues)
|
17
|
+
allow(Hutch::Waiter).to receive(:wait_until_signaled)
|
18
|
+
allow(broker).to receive(:stop)
|
19
|
+
|
20
|
+
worker.run
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#setup_queues' do
|
25
|
+
it 'sets up queues for each of the consumers' do
|
26
|
+
consumers.each do |consumer|
|
27
|
+
expect(worker).to receive(:setup_queue).with(consumer)
|
28
|
+
end
|
29
|
+
worker.setup_queues
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#setup_queue' do
|
34
|
+
let(:queue) { double('Queue', bind: nil, subscribe: nil) }
|
35
|
+
before { allow(broker).to receive_messages(queue: queue, bind_queue: nil) }
|
36
|
+
|
37
|
+
it 'creates a queue' do
|
38
|
+
expect(broker).to receive(:queue).with(consumer.get_queue_name, consumer.get_options).and_return(queue)
|
39
|
+
worker.setup_queue(consumer)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'binds the queue to each of the routing keys' do
|
43
|
+
expect(broker).to receive(:bind_queue).with(queue, %w( a b c ))
|
44
|
+
worker.setup_queue(consumer)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'sets up a subscription' do
|
48
|
+
expect(queue).to receive(:subscribe).with(consumer_tag: %r(^hutch\-.{36}$), manual_ack: true)
|
49
|
+
worker.setup_queue(consumer)
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'with a configured consumer tag prefix' do
|
53
|
+
before { Hutch::Config.set(:consumer_tag_prefix, 'appname') }
|
54
|
+
|
55
|
+
it 'sets up a subscription with the configured tag prefix' do
|
56
|
+
expect(queue).to receive(:subscribe).with(consumer_tag: %r(^appname\-.{36}$), manual_ack: true)
|
57
|
+
worker.setup_queue(consumer)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with a configured consumer tag prefix that is too long' do
|
62
|
+
let(:maximum_size) { 255 - SecureRandom.uuid.size - 1 }
|
63
|
+
before { Hutch::Config.set(:consumer_tag_prefix, 'a'.*(maximum_size + 1)) }
|
64
|
+
|
65
|
+
it 'raises an error' do
|
66
|
+
expect { worker.setup_queue(consumer) }.to raise_error(/Tag must be 255 bytes long at most/)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#handle_message' do
|
72
|
+
let(:payload) { '{}' }
|
73
|
+
let(:consumer_instance) { double('Consumer instance') }
|
74
|
+
let(:delivery_info) { double('Delivery Info', routing_key: '',
|
75
|
+
delivery_tag: 'dt') }
|
76
|
+
let(:properties) { double('Properties', message_id: nil, content_type: "application/json") }
|
77
|
+
before { allow(consumer).to receive_messages(new: consumer_instance) }
|
78
|
+
before { allow(broker).to receive(:ack) }
|
79
|
+
before { allow(broker).to receive(:nack) }
|
80
|
+
before { allow(consumer_instance).to receive(:broker=) }
|
81
|
+
before { allow(consumer_instance).to receive(:delivery_info=) }
|
82
|
+
|
83
|
+
it 'passes the message to the consumer' do
|
84
|
+
expect(consumer_instance).to receive(:process).
|
85
|
+
with(an_instance_of(Hutch::Message))
|
86
|
+
expect(consumer_instance).to receive(:message_rejected?).and_return(false)
|
87
|
+
worker.handle_message(consumer, delivery_info, properties, payload)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'acknowledges the message' do
|
91
|
+
allow(consumer_instance).to receive(:process)
|
92
|
+
expect(broker).to receive(:ack).with(delivery_info.delivery_tag)
|
93
|
+
expect(consumer_instance).to receive(:message_rejected?).and_return(false)
|
94
|
+
worker.handle_message(consumer, delivery_info, properties, payload)
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'when the consumer fails and a requeue is configured' do
|
98
|
+
|
99
|
+
it 'requeues the message' do
|
100
|
+
allow(consumer_instance).to receive(:process).and_raise('failed')
|
101
|
+
requeuer = double
|
102
|
+
allow(requeuer).to receive(:handle) { |delivery_info, properties, broker, e|
|
103
|
+
broker.requeue delivery_info.delivery_tag
|
104
|
+
true
|
105
|
+
}
|
106
|
+
allow(worker).to receive(:error_acknowledgements).and_return([requeuer])
|
107
|
+
expect(broker).to_not receive(:ack)
|
108
|
+
expect(broker).to_not receive(:nack)
|
109
|
+
expect(broker).to receive(:requeue)
|
110
|
+
|
111
|
+
worker.handle_message(consumer, delivery_info, properties, payload)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
context 'when the consumer raises an exception' do
|
117
|
+
before { allow(consumer_instance).to receive(:process).and_raise('a consumer error') }
|
118
|
+
|
119
|
+
it 'logs the error' do
|
120
|
+
Hutch::Config[:error_handlers].each do |backend|
|
121
|
+
expect(backend).to receive(:handle)
|
122
|
+
end
|
123
|
+
worker.handle_message(consumer, delivery_info, properties, payload)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'rejects the message' do
|
127
|
+
expect(broker).to receive(:nack).with(delivery_info.delivery_tag)
|
128
|
+
worker.handle_message(consumer, delivery_info, properties, payload)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "when the payload is not valid json" do
|
133
|
+
let(:payload) { "Not Valid JSON" }
|
134
|
+
|
135
|
+
it 'logs the error' do
|
136
|
+
Hutch::Config[:error_handlers].each do |backend|
|
137
|
+
expect(backend).to receive(:handle)
|
138
|
+
end
|
139
|
+
worker.handle_message(consumer, delivery_info, properties, payload)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'rejects the message' do
|
143
|
+
expect(broker).to receive(:nack).with(delivery_info.delivery_tag)
|
144
|
+
worker.handle_message(consumer, delivery_info, properties, payload)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
describe '#acknowledge_error' do
|
151
|
+
let(:delivery_info) { double('Delivery Info', routing_key: '',
|
152
|
+
delivery_tag: 'dt') }
|
153
|
+
let(:properties) { double('Properties', message_id: 'abc123') }
|
154
|
+
|
155
|
+
subject { worker.acknowledge_error delivery_info, properties, broker, StandardError.new }
|
156
|
+
|
157
|
+
it 'stops when it runs a successful acknowledgement' do
|
158
|
+
skip_ack = double handle: false
|
159
|
+
always_ack = double handle: true
|
160
|
+
never_used = double handle: true
|
161
|
+
|
162
|
+
allow(worker).
|
163
|
+
to receive(:error_acknowledgements).
|
164
|
+
and_return([skip_ack, always_ack, never_used])
|
165
|
+
|
166
|
+
expect(never_used).to_not receive(:handle)
|
167
|
+
|
168
|
+
subject
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'defaults to nacking' do
|
172
|
+
skip_ack = double handle: false
|
173
|
+
|
174
|
+
allow(worker).
|
175
|
+
to receive(:error_acknowledgements).
|
176
|
+
and_return([skip_ack, skip_ack])
|
177
|
+
|
178
|
+
expect(broker).to receive(:nack)
|
179
|
+
|
180
|
+
subject
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
data/spec/hutch_spec.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hutch do
|
4
|
+
describe '.register_consumer' do
|
5
|
+
let(:consumer_a) { double('Consumer') }
|
6
|
+
let(:consumer_b) { double('Consumer') }
|
7
|
+
|
8
|
+
it 'saves the consumers in the global consumer list' do
|
9
|
+
Hutch.register_consumer(consumer_a)
|
10
|
+
Hutch.register_consumer(consumer_b)
|
11
|
+
expect(Hutch.consumers).to include consumer_a
|
12
|
+
expect(Hutch.consumers).to include consumer_b
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '.connect' do
|
17
|
+
context 'not connected' do
|
18
|
+
let(:options) { double 'options' }
|
19
|
+
let(:config) { double 'config' }
|
20
|
+
let(:broker) { double 'broker' }
|
21
|
+
let(:action) { Hutch.connect(options, config) }
|
22
|
+
|
23
|
+
it 'passes options and config' do
|
24
|
+
expect(Hutch::Broker).to receive(:new).with(config).and_return broker
|
25
|
+
expect(broker).to receive(:connect).with options
|
26
|
+
|
27
|
+
action
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'connected' do
|
33
|
+
before { allow(Hutch).to receive(:connected?).and_return true }
|
34
|
+
|
35
|
+
it 'does not reconnect' do
|
36
|
+
expect(Hutch::Broker).not_to receive :new
|
37
|
+
Hutch.connect
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '.connected?' do
|
43
|
+
subject(:connected?) { Hutch.connected? }
|
44
|
+
|
45
|
+
before { allow(Hutch).to receive(:broker).and_return(broker) }
|
46
|
+
|
47
|
+
context 'without a broker' do
|
48
|
+
let(:broker) { nil }
|
49
|
+
|
50
|
+
it { expect(connected?).to be_falsey }
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'without a connection' do
|
54
|
+
let(:connection) { nil }
|
55
|
+
let(:broker) { double(:broker, connection: connection) }
|
56
|
+
|
57
|
+
it { expect(connected?).to be_falsey }
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'with a closed connection' do
|
61
|
+
let(:connection) { double(:connection, open?: false) }
|
62
|
+
let(:broker) { double(:broker, connection: connection) }
|
63
|
+
|
64
|
+
it { expect(connected?).to be_falsey }
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'with an opened connection' do
|
68
|
+
let(:connection) { double(:connection, open?: true) }
|
69
|
+
let(:broker) { double(:broker, connection: connection) }
|
70
|
+
|
71
|
+
it { expect(connected?).to be_truthy }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#publish' do
|
76
|
+
let(:broker) { double(Hutch::Broker) }
|
77
|
+
let(:args) { ['test.key', 'message', { headers: { foo: 'bar' } }] }
|
78
|
+
|
79
|
+
before { allow(Hutch).to receive(:broker).and_return(broker) }
|
80
|
+
|
81
|
+
it 'delegates to Hutch::Broker#publish' do
|
82
|
+
expect(broker).to receive(:publish).with(*args)
|
83
|
+
Hutch.publish(*args)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
if ENV['TRAVIS']
|
3
|
+
require 'coveralls'
|
4
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
5
|
+
end
|
6
|
+
|
7
|
+
SimpleCov.start do
|
8
|
+
add_filter '/spec/'
|
9
|
+
add_filter '/.bundle/'
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'raven'
|
13
|
+
require 'hutch'
|
14
|
+
require 'logger'
|
15
|
+
|
16
|
+
# set logger to be a null logger
|
17
|
+
Hutch::Logging.logger = Logger.new(File::NULL)
|
18
|
+
|
19
|
+
RSpec.configure do |config|
|
20
|
+
config.raise_errors_for_deprecations!
|
21
|
+
|
22
|
+
if defined?(JRUBY_VERSION)
|
23
|
+
config.filter_run_excluding adapter: :bunny
|
24
|
+
else
|
25
|
+
config.filter_run_excluding adapter: :march_hare
|
26
|
+
end
|
27
|
+
|
28
|
+
config.mock_with :rspec do |mocks|
|
29
|
+
mocks.verify_partial_doubles = true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Constants (classes, etc) defined within a block passed to this method
|
34
|
+
# will be removed from the global namespace after the block as run.
|
35
|
+
def isolate_constants
|
36
|
+
existing_constants = Object.constants
|
37
|
+
yield
|
38
|
+
ensure
|
39
|
+
(Object.constants - existing_constants).each do |constant|
|
40
|
+
Object.send(:remove_const, constant)
|
41
|
+
end
|
42
|
+
end
|
File without changes
|
File without changes
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<% if object['setting_rows'] %>
|
2
|
+
<h2>
|
3
|
+
Configuration
|
4
|
+
</h2>
|
5
|
+
|
6
|
+
<div class="tags">
|
7
|
+
<table border="1" class="settings">
|
8
|
+
<thead>
|
9
|
+
<tr>
|
10
|
+
<th>
|
11
|
+
Setting name
|
12
|
+
</th>
|
13
|
+
<th>
|
14
|
+
Default value
|
15
|
+
</th>
|
16
|
+
<th>
|
17
|
+
Type
|
18
|
+
</th>
|
19
|
+
<th>
|
20
|
+
ENV variable
|
21
|
+
</th>
|
22
|
+
<th>
|
23
|
+
Description
|
24
|
+
</th>
|
25
|
+
</tr>
|
26
|
+
</thead>
|
27
|
+
<tbody>
|
28
|
+
<% for setting in object['setting_rows'] %>
|
29
|
+
<tr>
|
30
|
+
<td><tt><%= resolve_links "{Hutch::Config##{setting[:name]} #{setting[:name]}}" %></tt></td>
|
31
|
+
<td><%= setting[:default_value] %></td>
|
32
|
+
<td><%= setting[:type] %></td>
|
33
|
+
<td><tt>HUTCH_<%= setting[:name].upcase %></tt></td>
|
34
|
+
<td><%= html_markup_markdown setting[:first_line_of_description] %></td>
|
35
|
+
</tr>
|
36
|
+
<% end %>
|
37
|
+
</tbody>
|
38
|
+
</table>
|
39
|
+
</div>
|
40
|
+
<% end %>
|