basquiat 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.metrics +5 -0
- data/.reek +3 -0
- data/.rspec +1 -0
- data/.rubocop.yml +2 -1
- data/.ruby-version +1 -1
- data/Guardfile +5 -4
- data/README.md +10 -8
- data/basquiat.gemspec +10 -8
- data/basquiat_docker.sh +35 -0
- data/docker-compose.yml +5 -1
- data/docker/Dockerfile +2 -3
- data/docker/guard_start.sh +3 -0
- data/lib/basquiat.rb +5 -0
- data/lib/basquiat/adapters/base_adapter.rb +21 -11
- data/lib/basquiat/adapters/base_message.rb +29 -0
- data/lib/basquiat/adapters/rabbitmq/configuration.rb +52 -0
- data/lib/basquiat/adapters/rabbitmq/connection.rb +89 -0
- data/lib/basquiat/adapters/rabbitmq/events.rb +49 -0
- data/lib/basquiat/adapters/rabbitmq/message.rb +33 -0
- data/lib/basquiat/adapters/rabbitmq/requeue_strategies.rb +3 -0
- data/lib/basquiat/adapters/rabbitmq/requeue_strategies/base_strategy.rb +33 -0
- data/lib/basquiat/adapters/rabbitmq/requeue_strategies/basic_acknowledge.rb +12 -0
- data/lib/basquiat/adapters/rabbitmq/requeue_strategies/dead_lettering.rb +58 -0
- data/lib/basquiat/adapters/rabbitmq/requeue_strategies/delayed_delivery.rb +27 -0
- data/lib/basquiat/adapters/rabbitmq/session.rb +47 -0
- data/lib/basquiat/adapters/rabbitmq_adapter.rb +39 -95
- data/lib/basquiat/adapters/test_adapter.rb +4 -3
- data/lib/basquiat/errors.rb +2 -0
- data/lib/basquiat/errors/strategy_not_registered.rb +14 -0
- data/lib/basquiat/errors/subclass_responsibility.rb +9 -0
- data/lib/basquiat/interfaces/base.rb +0 -1
- data/lib/basquiat/support/configuration.rb +4 -4
- data/lib/basquiat/support/hash_refinements.rb +2 -1
- data/lib/basquiat/version.rb +1 -1
- data/spec/lib/adapters/base_adapter_spec.rb +24 -6
- data/spec/lib/adapters/base_message_spec.rb +16 -0
- data/spec/lib/adapters/rabbitmq/configuration_spec.rb +47 -0
- data/spec/lib/adapters/rabbitmq/connection_spec.rb +45 -0
- data/spec/lib/adapters/rabbitmq/events_spec.rb +78 -0
- data/spec/lib/adapters/rabbitmq/message_spec.rb +26 -0
- data/spec/lib/adapters/rabbitmq/requeue_strategies/basic_acknowledge_spec.rb +38 -0
- data/spec/lib/adapters/rabbitmq/requeue_strategies/dead_lettering_spec.rb +102 -0
- data/spec/lib/adapters/rabbitmq_adapter_spec.rb +39 -49
- data/spec/lib/adapters/test_adapter_spec.rb +15 -19
- data/spec/lib/support/configuration_spec.rb +1 -1
- data/spec/lib/support/hash_refinements_spec.rb +8 -2
- data/spec/spec_helper.rb +8 -5
- data/spec/support/rabbitmq_queue_matchers.rb +53 -0
- data/spec/support/shared_examples/basquiat_adapter_shared_examples.rb +9 -20
- metadata +65 -6
- data/.travis.yml +0 -3
- data/docker/basquiat_start.sh +0 -9
@@ -3,6 +3,7 @@ require 'naught'
|
|
3
3
|
require 'erb'
|
4
4
|
|
5
5
|
module Basquiat
|
6
|
+
require 'logger'
|
6
7
|
DefaultLogger = Naught.build { |config| config.mimic Logger }
|
7
8
|
|
8
9
|
class Configuration
|
@@ -40,18 +41,17 @@ module Basquiat
|
|
40
41
|
end
|
41
42
|
|
42
43
|
def reload_classes
|
43
|
-
Basquiat::Base.descendants.each
|
44
|
-
klass.reload_adapter_from_configuration
|
45
|
-
end
|
44
|
+
Basquiat::Base.descendants.each(&:reload_adapter_from_configuration)
|
46
45
|
end
|
47
46
|
|
48
47
|
private
|
48
|
+
|
49
49
|
def config
|
50
50
|
@yaml.fetch(environment)
|
51
51
|
end
|
52
52
|
|
53
53
|
def load_yaml(path)
|
54
|
-
@yaml
|
54
|
+
@yaml = YAML.load(ERB.new(IO.readlines(path).join).result).symbolize_keys
|
55
55
|
end
|
56
56
|
|
57
57
|
def setup_basic_options
|
@@ -10,12 +10,13 @@ module Basquiat
|
|
10
10
|
self[key] = value
|
11
11
|
end
|
12
12
|
end
|
13
|
+
self
|
13
14
|
end
|
14
15
|
|
15
16
|
def symbolize_keys
|
16
17
|
each_with_object({}) do |(key, value), new_hash|
|
17
18
|
new_key = key.to_sym rescue key
|
18
|
-
new_value
|
19
|
+
new_value = (value.is_a? Hash) ? value.symbolize_keys : value
|
19
20
|
new_hash[new_key] = new_value
|
20
21
|
end
|
21
22
|
end
|
data/lib/basquiat/version.rb
CHANGED
@@ -1,11 +1,29 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
# Sample class used for testing
|
4
|
-
class SampleAdapter
|
5
|
-
include Basquiat::Adapters::Base
|
6
|
-
end
|
7
|
-
|
8
4
|
describe Basquiat::Adapters::Base do
|
9
|
-
subject {
|
10
|
-
|
5
|
+
subject(:adapter) { Basquiat::Adapters::Base.new }
|
6
|
+
|
7
|
+
[:disconnect, :subscribe_to, :publish].each do |meth|
|
8
|
+
it "raise a SubclassResponsibility error if #{meth} isn't implemented" do
|
9
|
+
expect { adapter.public_send(meth) }.to raise_error Basquiat::Errors::SubclassResponsibility
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'raise error when using an unregistered strategy' do
|
14
|
+
# expect(adapter.use_strategy(:not_here)).to raise_error StrategyNotRegistered
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'register a requeue strategy' do
|
18
|
+
class CoolStuff
|
19
|
+
end
|
20
|
+
adapter.class.register_strategy :cool_stuff, CoolStuff
|
21
|
+
expect(adapter.strategies).to have_key :cool_stuff
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'merges the options with the default ones' do
|
25
|
+
opts = adapter.instance_variable_get(:@options)
|
26
|
+
adapter.adapter_options(nice_option: '127.0.0.2')
|
27
|
+
expect(opts[:nice_option]).to eq('127.0.0.2')
|
28
|
+
end
|
11
29
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Basquiat::Adapters::BaseMessage do
|
4
|
+
subject(:message) { Basquiat::Adapters::BaseMessage.new({ data: 'everything is AWESOME!' }.to_json) }
|
5
|
+
|
6
|
+
it 'delegates calls to the JSON' do
|
7
|
+
expect(message.fetch(:data)).to eq('everything is AWESOME!')
|
8
|
+
expect { message.fetch(:error) }.to raise_error KeyError
|
9
|
+
end
|
10
|
+
|
11
|
+
[:ack?, :unack, :requeue, :delay_redelivery].each do |meth|
|
12
|
+
it "raise a SubclassResponsibility error if #{meth} isn't implemented" do
|
13
|
+
expect { message.public_send(meth) }.to raise_error Basquiat::Errors::SubclassResponsibility
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'basquiat/adapters/rabbitmq_adapter'
|
3
|
+
|
4
|
+
class AwesomeStrategy < Basquiat::Adapters::RabbitMq::BaseStrategy
|
5
|
+
def self.session_options
|
6
|
+
{ exchange: { options: { some_setting: 'awesomesauce' } } }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Basquiat::Adapters::RabbitMq::Configuration do
|
11
|
+
subject(:config) { Basquiat::Adapters::RabbitMq::Configuration.new }
|
12
|
+
|
13
|
+
# used by the Adapter::Base class
|
14
|
+
describe '#merge_user_options', focus: true do
|
15
|
+
it 'merges the user supplied options with the default ones' do
|
16
|
+
config.merge_user_options(queue: { name: 'config.test.queue' })
|
17
|
+
expect(config.base_options[:queue][:name]).to eq('config.test.queue')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it '#connection_options' do
|
22
|
+
expect(config.connection_options.keys).to contain_exactly(:servers, :auth, :failover)
|
23
|
+
end
|
24
|
+
|
25
|
+
it '#session_options' do
|
26
|
+
expect(config.session_options.keys).to contain_exactly(:exchange, :queue, :publisher)
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'Strategies' do
|
30
|
+
it 'merges the strategy options with the session ones' do
|
31
|
+
Basquiat::Adapters::RabbitMq.register_strategy(:awesome, AwesomeStrategy)
|
32
|
+
config.merge_user_options(requeue: { enabled: true, strategy: 'awesome' })
|
33
|
+
expect(config.session_options[:exchange][:options]).to have_key(:some_setting)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'raises an error if trying to use a non-registered strategy' do
|
37
|
+
config.merge_user_options(requeue: { enabled: true, strategy: 'perfect' })
|
38
|
+
expect { config.strategy }.to raise_error Basquiat::Errors::StrategyNotRegistered
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'deals with the requeue strategy options', focus: true do
|
42
|
+
Basquiat::Adapters::RabbitMq.register_strategy :dlx, Basquiat::Adapters::RabbitMq::DeadLettering
|
43
|
+
config.merge_user_options(requeue: { enabled: true, strategy: 'dlx', options: { exchange: 'dlx.topic' } })
|
44
|
+
expect(config.session_options[:queue][:options]).to include('x-dead-letter-exchange' => 'dlx.topic')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'basquiat/adapters/rabbitmq_adapter'
|
3
|
+
|
4
|
+
describe Basquiat::Adapters::RabbitMq::Connection do
|
5
|
+
subject(:connection) { Basquiat::Adapters::RabbitMq::Connection }
|
6
|
+
|
7
|
+
let(:servers) do
|
8
|
+
[{ host: ENV.fetch('BASQUIAT_RABBITMQ_1_PORT_5672_TCP_ADDR') { 'localhost' },
|
9
|
+
port: ENV.fetch('BASQUIAT_RABBITMQ_1_PORT_5672_TCP_PORT') { 5672 } }]
|
10
|
+
end
|
11
|
+
|
12
|
+
before(:each) do
|
13
|
+
Basquiat.configure { |c| c.logger = Logger.new('log/basquiat.log') }
|
14
|
+
end
|
15
|
+
|
16
|
+
it '#connected?' do
|
17
|
+
conn = connection.new(servers: servers)
|
18
|
+
expect(conn.connected?).to be_falsey
|
19
|
+
conn.start
|
20
|
+
expect(conn.connected?).to_not be_truthy
|
21
|
+
conn.disconnect
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'failover' do
|
25
|
+
let(:failover) do
|
26
|
+
{ default_timeout: 0.2, max_retries: 2, threaded: false }
|
27
|
+
end
|
28
|
+
|
29
|
+
before(:each) { servers.unshift(host: 'localhost', port: 1234) }
|
30
|
+
|
31
|
+
it 'tries a reconnection after a few seconds' do
|
32
|
+
conn = connection.new(servers: [host: 'localhost', port: 1234],
|
33
|
+
failover: { default_timeout: 0.2, max_retries: 1 })
|
34
|
+
expect { conn.start }.to raise_error(Bunny::TCPConnectionFailed)
|
35
|
+
conn.close
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'uses another server after all retries on a single one' do
|
39
|
+
conn = connection.new(servers: servers, failover: failover)
|
40
|
+
expect { conn.start }.to_not raise_error
|
41
|
+
expect(conn.current_server_uri).to match "#{ENV.fetch('BASQUIAT_RABBITMQ_1_PORT_5672_TCP_PORT') { 5672 }}"
|
42
|
+
conn.close
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'basquiat/adapters/rabbitmq_adapter'
|
3
|
+
|
4
|
+
describe Basquiat::Adapters::RabbitMq::Events do
|
5
|
+
subject(:events) { Basquiat::Adapters::RabbitMq::Events.new }
|
6
|
+
|
7
|
+
context 'basic functionality' do
|
8
|
+
it 'raises a KeyError when no matching keys are found' do
|
9
|
+
expect { events['event'] }.to raise_error KeyError
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'stores the key and value of the proc' do
|
13
|
+
proc = -> { 'equal awesome lambda' }
|
14
|
+
events['some.awesome.event'] = proc
|
15
|
+
expect(events['some.awesome.event']).to eq proc
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'wildcard keys' do
|
20
|
+
let(:proc) { -> { 'Hello from the lambda! o/' } }
|
21
|
+
describe '*' do
|
22
|
+
let(:words) { %w(awesome lame dumb cool) }
|
23
|
+
context 'matches any ONE word' do
|
24
|
+
it 'at the end' do
|
25
|
+
events['some.event.*'] = proc
|
26
|
+
words.each do |word|
|
27
|
+
expect(events["some.event.#{word}"]).to eq proc
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'in the middle of the name' do
|
32
|
+
events['some.*.event'] = proc
|
33
|
+
words.each do |word|
|
34
|
+
expect(events["some.#{word}.event"]).to eq proc
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'at the start' do
|
39
|
+
events['*.some.event'] = proc
|
40
|
+
words.each do |word|
|
41
|
+
expect(events["#{word}.some.event"]).to eq proc
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'in more than one place' do
|
46
|
+
events['some.*.bob.*'] = proc
|
47
|
+
words.each do |word|
|
48
|
+
expect(events["some.#{word}.bob.#{word}"]).to eq(proc)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
context 'does not match more than ONE word' do
|
53
|
+
it 'some.* does not match some.event.dude' do
|
54
|
+
events['some.*'] = -> {}
|
55
|
+
expect { events['some.event.dude'] }.to raise_error KeyError
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
describe '#' do
|
60
|
+
context 'matches any number of words' do
|
61
|
+
it '# matches all events' do
|
62
|
+
events['#'] = proc
|
63
|
+
%w(some.cool.event event cool.event).each do |event|
|
64
|
+
expect(events[event]).to eq(proc)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'matches specific events' do
|
69
|
+
events['#.event'] = proc
|
70
|
+
%w(some.cool.event cool.event).each do |event|
|
71
|
+
expect(events[event]).to eq(proc)
|
72
|
+
end
|
73
|
+
expect { events['event']}.to raise_error KeyError
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'basquiat/adapters/rabbitmq_adapter'
|
3
|
+
|
4
|
+
describe Basquiat::Adapters::RabbitMq::Message do
|
5
|
+
let(:json) do
|
6
|
+
{ key: 'value', date: Date.new.iso8601 }.to_json
|
7
|
+
end
|
8
|
+
subject(:message) { Basquiat::Adapters::RabbitMq::Message.new(json) }
|
9
|
+
|
10
|
+
it 'delegates all calls to message hash' do
|
11
|
+
expect(message[:key]).to eq('value')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'can be JSONified' do
|
15
|
+
expect(MultiJson.dump(message)).to eq(json)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'exposes the delivery information' do
|
19
|
+
expect { message.di }.to_not raise_error
|
20
|
+
expect { message.delivery_info }.to_not raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'exposes the properties of the message' do
|
24
|
+
expect { message.props }.to_not raise_error
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'basquiat/adapters/rabbitmq_adapter'
|
3
|
+
|
4
|
+
describe 'Requeue Strategies' do
|
5
|
+
let(:adapter) { Basquiat::Adapters::RabbitMq.new }
|
6
|
+
let(:base_options) do
|
7
|
+
{ servers: [{ host: ENV.fetch('BASQUIAT_RABBITMQ_1_PORT_5672_TCP_ADDR') { 'localhost' },
|
8
|
+
port: ENV.fetch('BASQUIAT_RABBITMQ_1_PORT_5672_TCP_PORT') { 5672 } }],
|
9
|
+
publisher: { persistent: true } }
|
10
|
+
end
|
11
|
+
|
12
|
+
before(:each) { adapter.adapter_options(base_options) }
|
13
|
+
after(:each) { remove_queues_and_exchanges(adapter) }
|
14
|
+
|
15
|
+
describe 'BasickAcknowledge (aka the default)' do
|
16
|
+
it 'acks a message by default' do
|
17
|
+
adapter.subscribe_to('some.event', ->(_) { 'Everything is AWESOME!' })
|
18
|
+
adapter.listen(block: false)
|
19
|
+
|
20
|
+
adapter.publish('some.event', data: 'stupid message')
|
21
|
+
sleep 0.7 # Wait for the listening thread.
|
22
|
+
|
23
|
+
expect(adapter.session.queue.message_count).to eq(0)
|
24
|
+
expect(adapter.session.queue).to_not have_unacked_messages
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'support declared acks' do
|
28
|
+
adapter.subscribe_to('some.event', ->(msg) { msg.ack })
|
29
|
+
adapter.listen(block: false)
|
30
|
+
|
31
|
+
adapter.publish('some.event', data: 'stupid message')
|
32
|
+
sleep 0.7 # Wait for the listening thread.
|
33
|
+
|
34
|
+
expect(adapter.session.queue.message_count).to eq(0)
|
35
|
+
expect(adapter.session.queue).to_not have_unacked_messages
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'basquiat/adapters/rabbitmq_adapter'
|
3
|
+
|
4
|
+
describe Basquiat::Adapters::RabbitMq::DeadLettering do
|
5
|
+
let(:adapter) { Basquiat::Adapters::RabbitMq.new }
|
6
|
+
let(:base_options) do
|
7
|
+
{ servers: [{ host: ENV.fetch('BASQUIAT_RABBITMQ_1_PORT_5672_TCP_ADDR') { 'localhost' },
|
8
|
+
port: ENV.fetch('BASQUIAT_RABBITMQ_1_PORT_5672_TCP_PORT') { 5672 } }],
|
9
|
+
publisher: { persistent: true } }
|
10
|
+
end
|
11
|
+
|
12
|
+
before(:each) do
|
13
|
+
adapter.adapter_options(base_options)
|
14
|
+
adapter.class.register_strategy :dlx, Basquiat::Adapters::RabbitMq::DeadLettering
|
15
|
+
end
|
16
|
+
|
17
|
+
after(:each) { remove_queues_and_exchanges(adapter) }
|
18
|
+
|
19
|
+
it 'creates the dead letter exchange' do
|
20
|
+
adapter.adapter_options(requeue: { enabled: true, strategy: 'dlx' })
|
21
|
+
adapter.strategy # initialize the strategy
|
22
|
+
channel = adapter.session.channel
|
23
|
+
expect(channel.exchanges.keys).to contain_exactly('my.test_exchange', 'basquiat.dlx')
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'creates and binds a dead letter queue' do
|
27
|
+
# Initialize the strategy since we won't be listening to anything
|
28
|
+
adapter.adapter_options(requeue: { enabled: true, strategy: 'dlx' })
|
29
|
+
session = adapter.session
|
30
|
+
adapter.strategy
|
31
|
+
|
32
|
+
# Grabs the Bunny::Channel from the session for checks
|
33
|
+
channel = session.channel
|
34
|
+
expect(channel.queues.keys).to include('basquiat.dlq')
|
35
|
+
expect(channel.queues['basquiat.dlq'].arguments)
|
36
|
+
.to match(hash_including('x-dead-letter-exchange' => session.exchange.name, 'x-message-ttl' => 1000))
|
37
|
+
expect(session.queue.arguments).to match(hash_including('x-dead-letter-exchange' => 'basquiat.dlx'))
|
38
|
+
|
39
|
+
expect do
|
40
|
+
channel.exchanges['basquiat.dlx'].publish('some message', routing_key: 'some.event')
|
41
|
+
sleep 0.1
|
42
|
+
end.to change { channel.queues['basquiat.dlq'].message_count }.by(1)
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'if it was the queue that unacked the message then' do
|
46
|
+
before(:each) do
|
47
|
+
adapter.adapter_options(requeue: { enabled: true, strategy: 'dlx' })
|
48
|
+
session = adapter.session
|
49
|
+
adapter.strategy # initialize strategy
|
50
|
+
|
51
|
+
queue = session.channel.queue('sample_queue', arguments: { 'x-dead-letter-exchange' => 'basquiat.dlx' })
|
52
|
+
queue.bind(session.exchange, routing_key: 'sample.message')
|
53
|
+
|
54
|
+
queue.subscribe(manual_ack: true, block: false) do |di, _, _|
|
55
|
+
adapter.session.channel.ack(di.delivery_tag)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'process the message' do
|
60
|
+
sample = 0
|
61
|
+
adapter.subscribe_to('sample.message', ->(msg) do
|
62
|
+
sample += 1
|
63
|
+
sample == 3 ? msg.ack : msg.unack
|
64
|
+
end)
|
65
|
+
|
66
|
+
adapter.listen(block: false)
|
67
|
+
adapter.publish('sample.message', key: 'message')
|
68
|
+
|
69
|
+
sleep 3
|
70
|
+
expect(sample).to eq(3)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'else drop the message' do
|
74
|
+
ack_count = 0
|
75
|
+
sample = 0
|
76
|
+
|
77
|
+
other = Basquiat::Adapters::RabbitMq.new
|
78
|
+
other.adapter_options(base_options.merge(queue: { name: 'other_queue' }, requeue: { enabled: true, strategy: 'dlx' }))
|
79
|
+
other.subscribe_to('sample.message', ->(msg) do
|
80
|
+
ack_count += 1
|
81
|
+
end)
|
82
|
+
|
83
|
+
adapter.subscribe_to('sample.message', ->(msg) do
|
84
|
+
if sample == 3
|
85
|
+
msg.ack
|
86
|
+
else
|
87
|
+
sample += 1;
|
88
|
+
msg.unack
|
89
|
+
end
|
90
|
+
end)
|
91
|
+
|
92
|
+
other.listen(block: false)
|
93
|
+
adapter.listen(block: false)
|
94
|
+
adapter.publish('sample.message', key: 'message')
|
95
|
+
|
96
|
+
sleep 3
|
97
|
+
remove_queues_and_exchanges(other)
|
98
|
+
expect(ack_count).to eq(1)
|
99
|
+
expect(sample).to eq(3)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|