liebre 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +51 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +47 -0
- data/LICENSE +22 -0
- data/README.md +268 -0
- data/lib/liebre.rb +24 -0
- data/lib/liebre/common.rb +7 -0
- data/lib/liebre/common/utils.rb +24 -0
- data/lib/liebre/config.rb +48 -0
- data/lib/liebre/connection_manager.rb +64 -0
- data/lib/liebre/publisher.rb +88 -0
- data/lib/liebre/runner.rb +59 -0
- data/lib/liebre/runner/consumers.rb +36 -0
- data/lib/liebre/runner/starter.rb +40 -0
- data/lib/liebre/runner/starter/consumer.rb +91 -0
- data/lib/liebre/runner/starter/consumer/handler.rb +35 -0
- data/lib/liebre/runner/starter/resources.rb +39 -0
- data/lib/liebre/runner/starter/resources/queue_builder.rb +58 -0
- data/lib/liebre/runner/starter/rpc.rb +45 -0
- data/lib/liebre/tasks.rb +12 -0
- data/lib/liebre/version.rb +5 -0
- data/liebre.gemspec +26 -0
- data/spec/config/liebre.yml +47 -0
- data/spec/config/rabbitmq.yml +35 -0
- data/spec/integration_spec.rb +73 -0
- data/spec/liebre/config_spec.rb +62 -0
- data/spec/liebre/connection_manager_spec.rb +40 -0
- data/spec/liebre/publisher_spec.rb +86 -0
- data/spec/liebre/runner/consumers_spec.rb +59 -0
- data/spec/liebre/runner/starter/consumer_spec.rb +140 -0
- data/spec/liebre/runner/starter/resources/queue_builder_spec.rb +69 -0
- data/spec/liebre/runner/starter/resources_spec.rb +36 -0
- data/spec/liebre/runner/starter/rpc_spec.rb +92 -0
- data/spec/liebre/runner/starter_spec.rb +59 -0
- data/spec/liebre/runner_spec.rb +50 -0
- data/spec/spec_helper.rb +23 -0
- metadata +172 -0
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Liebre::Publisher do
|
4
|
+
|
5
|
+
let :exchange_config do
|
6
|
+
{
|
7
|
+
'name' => "test_exchange",
|
8
|
+
'type' => "direct",
|
9
|
+
'opts' => {
|
10
|
+
'durable' => false
|
11
|
+
}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
let :publishers_config do
|
16
|
+
{
|
17
|
+
'test_publisher' => {
|
18
|
+
'exchange' =>
|
19
|
+
exchange_config
|
20
|
+
}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:channel) { double 'channel' }
|
25
|
+
let(:bunny_connection) { double 'bunny_conection', :create_channel => channel }
|
26
|
+
let(:connection_manager) { double 'connection_manager', :get => bunny_connection }
|
27
|
+
let(:exchange) { double 'exchange' }
|
28
|
+
|
29
|
+
before do
|
30
|
+
allow_any_instance_of(Liebre::Config).to receive(:publishers).and_return publishers_config
|
31
|
+
allow_any_instance_of(Liebre::Config).to receive(:rpc_request_timeout).and_return 10
|
32
|
+
|
33
|
+
expect(Liebre::ConnectionManager).to receive(:new).and_return connection_manager
|
34
|
+
expect(connection_manager).to receive(:ensure_started)
|
35
|
+
|
36
|
+
expect(Liebre::Common::Utils).to receive(:create_exchange).
|
37
|
+
with(channel, exchange_config).and_return exchange
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
subject { described_class.new 'test_publisher' }
|
42
|
+
|
43
|
+
describe "#enqueue" do
|
44
|
+
it do
|
45
|
+
message = "abc"
|
46
|
+
expect(exchange).to receive(:publish).with message, {}
|
47
|
+
|
48
|
+
subject.enqueue message
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#enqueue_and_wait" do
|
53
|
+
|
54
|
+
let(:correlation_id) { "correlation_id" }
|
55
|
+
let(:reply_queue_name) { "test_publisher_callback_#{correlation_id}" }
|
56
|
+
let(:reply_queue) { double "reply_queue", :name => reply_queue_name }
|
57
|
+
let(:delivery_info) { double "delivery_info", :consumer_tag => "tag"}
|
58
|
+
let(:consumer) { double 'consumer' }
|
59
|
+
let(:consumers) { {"tag" => consumer} }
|
60
|
+
|
61
|
+
before do
|
62
|
+
expect(channel).to receive(:queue).with(reply_queue_name, :exclusive => true).
|
63
|
+
and_return reply_queue
|
64
|
+
end
|
65
|
+
|
66
|
+
it do
|
67
|
+
message = "question"
|
68
|
+
answer = "answer"
|
69
|
+
expect(exchange).to receive(:publish).with message,
|
70
|
+
{:correlation_id => correlation_id, :reply_to => reply_queue_name}
|
71
|
+
|
72
|
+
expect(reply_queue).to receive(:subscribe).with(:block => true) do |&block|
|
73
|
+
expect(channel).to receive(:consumers).and_return consumers
|
74
|
+
expect(consumer).to receive(:cancel)
|
75
|
+
|
76
|
+
block.call(delivery_info, {:correlation_id => correlation_id}, answer)
|
77
|
+
end
|
78
|
+
|
79
|
+
expect(reply_queue).to receive(:delete)
|
80
|
+
|
81
|
+
result = subject.enqueue_and_wait message, :correlation_id => correlation_id
|
82
|
+
expect(result).to eq answer
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Liebre::Runner::Consumers do
|
4
|
+
|
5
|
+
let(:conn) { double 'conn' }
|
6
|
+
|
7
|
+
let(:first_expected_config) do
|
8
|
+
{
|
9
|
+
"class_name" => "MyConsumer",
|
10
|
+
"num_threads" => 3,
|
11
|
+
"rpc" => false
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:second_expected_config) do
|
16
|
+
{
|
17
|
+
"class_name" => "MyRPC",
|
18
|
+
"rpc" => true
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:consumers_config) do
|
23
|
+
{
|
24
|
+
"some_consumer" => first_expected_config,
|
25
|
+
"some_rpc" => second_expected_config
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
before do
|
30
|
+
allow(subject).to receive(:consumers).and_return consumers_config
|
31
|
+
end
|
32
|
+
|
33
|
+
subject { described_class.new(conn) }
|
34
|
+
|
35
|
+
describe "#consumer_names" do
|
36
|
+
it "returns all names" do
|
37
|
+
expect(subject.consumer_names).to eq ["some_consumer", "some_rpc"]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#start_all" do
|
42
|
+
let(:first_starter) { double 'first_starter' }
|
43
|
+
let(:second_starter) { double 'second_starter' }
|
44
|
+
|
45
|
+
it "starts the given consumers" do
|
46
|
+
expect(Liebre::Runner::Starter).to receive(:new).exactly(3).times.
|
47
|
+
with(conn, first_expected_config).and_return(first_starter)
|
48
|
+
|
49
|
+
expect(Liebre::Runner::Starter).to receive(:new).
|
50
|
+
with(conn, second_expected_config).and_return(second_starter)
|
51
|
+
|
52
|
+
expect(first_starter ).to receive(:call).exactly(3).times
|
53
|
+
expect(second_starter).to receive(:call)
|
54
|
+
|
55
|
+
subject.start_all
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Liebre::Runner::Starter::Consumer do
|
4
|
+
|
5
|
+
let(:connection) { double 'connection' }
|
6
|
+
|
7
|
+
let(:class_name) { "MyConsumer" }
|
8
|
+
let(:pool_size) { 4 }
|
9
|
+
|
10
|
+
let :config do
|
11
|
+
{
|
12
|
+
"class_name" => class_name,
|
13
|
+
"pool_size" => pool_size,
|
14
|
+
"rpc" => false,
|
15
|
+
"exchange" => {
|
16
|
+
"name" => "test_exchange",
|
17
|
+
"type" => "direct",
|
18
|
+
"opts" => {
|
19
|
+
"durable" => true
|
20
|
+
}
|
21
|
+
},
|
22
|
+
"queue" => {
|
23
|
+
"name" => "test_queue",
|
24
|
+
"opts" => {
|
25
|
+
"durable" => true
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
let :error_config do
|
32
|
+
{
|
33
|
+
"class_name" => class_name,
|
34
|
+
"pool_size" => pool_size,
|
35
|
+
"rpc" => false,
|
36
|
+
"exchange" => {
|
37
|
+
"name" => "test_exchange-error",
|
38
|
+
"type" => "direct",
|
39
|
+
"opts" => {
|
40
|
+
"durable" => true
|
41
|
+
}
|
42
|
+
},
|
43
|
+
"queue" => {
|
44
|
+
"name" => "test_queue-error",
|
45
|
+
"opts" => {
|
46
|
+
"durable" => true,
|
47
|
+
"exclusive" => true
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
let :parsed_config do
|
54
|
+
{
|
55
|
+
"class_name" => class_name,
|
56
|
+
"pool_size" => pool_size,
|
57
|
+
"rpc" => false,
|
58
|
+
"exchange" => {
|
59
|
+
"name" => "test_exchange",
|
60
|
+
"type" => "direct",
|
61
|
+
"opts" => {
|
62
|
+
"durable" => true
|
63
|
+
}
|
64
|
+
},
|
65
|
+
"queue" => {
|
66
|
+
"name" => "test_queue",
|
67
|
+
"opts" => {
|
68
|
+
"durable" => true,
|
69
|
+
"arguments" => {
|
70
|
+
'x-dead-letter-exchange' => "test_exchange-error"
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
let(:exchange) { double 'exchange' }
|
78
|
+
let(:queue) { double 'queue' }
|
79
|
+
let(:error_queue) { double 'error_queue' }
|
80
|
+
let(:channel) { double 'channel' }
|
81
|
+
let(:payload) { "the_payload" }
|
82
|
+
|
83
|
+
subject { described_class.new(connection, config) }
|
84
|
+
|
85
|
+
let :resources do
|
86
|
+
double 'resources', :exchange => exchange, :queue => queue, :channel => channel
|
87
|
+
end
|
88
|
+
|
89
|
+
let :error_resources do
|
90
|
+
double 'resources', :queue => error_queue
|
91
|
+
end
|
92
|
+
|
93
|
+
let(:class_name) { "MyConsumer" }
|
94
|
+
|
95
|
+
let(:consumer_class) { double 'consumer_class', :name => 'consumer_class' }
|
96
|
+
let(:consumer_instance) { double 'consumer_instance' }
|
97
|
+
|
98
|
+
let :meta do
|
99
|
+
double 'meta'
|
100
|
+
end
|
101
|
+
|
102
|
+
let(:handler) { double 'handler' }
|
103
|
+
|
104
|
+
let(:deliver_info) { double 'deliver_info' }
|
105
|
+
let(:ack) { :ack }
|
106
|
+
|
107
|
+
before do
|
108
|
+
expect(Liebre::Runner::Starter::Resources).to receive(:new).
|
109
|
+
with(connection, error_config).and_return(error_resources)
|
110
|
+
|
111
|
+
expect(Liebre::Runner::Starter::Resources).to receive(:new).
|
112
|
+
with(connection, parsed_config).and_return(resources)
|
113
|
+
|
114
|
+
stub_const(class_name, consumer_class)
|
115
|
+
|
116
|
+
expect(described_class::Handler).to receive(:new).
|
117
|
+
with(channel).and_return handler
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'creates error queue and creates and subscribes to standard queue' do
|
121
|
+
|
122
|
+
expect(queue).to receive :subscribe do |&block|
|
123
|
+
block.call(deliver_info, meta, payload)
|
124
|
+
end
|
125
|
+
|
126
|
+
expect(consumer_class).to receive :new do |given_payload, given_meta|
|
127
|
+
expect(given_payload).to eq payload
|
128
|
+
expect(given_meta ).to eq meta
|
129
|
+
|
130
|
+
consumer_instance
|
131
|
+
end
|
132
|
+
|
133
|
+
expect(consumer_instance).to receive(:call).and_return ack
|
134
|
+
|
135
|
+
expect(handler).to receive(:respond).with ack, deliver_info
|
136
|
+
|
137
|
+
subject.call
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Liebre::Runner::Starter::Resources::QueueBuilder do
|
4
|
+
|
5
|
+
let(:channel) { double 'channel' }
|
6
|
+
let(:routing_key) { "foo" }
|
7
|
+
|
8
|
+
let :config do
|
9
|
+
{
|
10
|
+
"queue" => {
|
11
|
+
"name" => "my_queue",
|
12
|
+
"opts" => {"some" => "option"}
|
13
|
+
},
|
14
|
+
"exchange" => {
|
15
|
+
"name" => "my_exchange",
|
16
|
+
"type" => "direct",
|
17
|
+
"opts" => {"an" => "option"}
|
18
|
+
},
|
19
|
+
"bind" => {"routing_key" => routing_key}
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:exchange) { double 'exchange' }
|
24
|
+
let(:queue) { double 'queue' }
|
25
|
+
|
26
|
+
subject { described_class.new(channel, config) }
|
27
|
+
|
28
|
+
describe '#call' do
|
29
|
+
|
30
|
+
it 'builds and binds the queue properly' do
|
31
|
+
expect(channel).to receive(:exchange).
|
32
|
+
with("my_exchange", :type => "direct", :an => "option").
|
33
|
+
and_return(exchange)
|
34
|
+
|
35
|
+
expect(channel).to receive(:queue).
|
36
|
+
with("my_queue", :some => "option").
|
37
|
+
and_return(queue)
|
38
|
+
|
39
|
+
expect(queue).to receive(:bind).
|
40
|
+
with(exchange, :routing_key => "foo")
|
41
|
+
|
42
|
+
expect(subject.queue).to eq queue
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "with multiple routing_keys" do
|
47
|
+
let(:routing_key) { %W{a b c} }
|
48
|
+
|
49
|
+
it 'builds and binds the queue properly' do
|
50
|
+
allow(channel).to receive(:exchange).
|
51
|
+
with("my_exchange", :type => "direct", :an => "option").
|
52
|
+
and_return(exchange)
|
53
|
+
|
54
|
+
expect(channel).to receive(:queue).
|
55
|
+
with("my_queue", :some => "option").
|
56
|
+
and_return(queue)
|
57
|
+
|
58
|
+
expect(queue).to receive(:bind).
|
59
|
+
with(exchange, :routing_key => "a")
|
60
|
+
expect(queue).to receive(:bind).
|
61
|
+
with(exchange, :routing_key => "b")
|
62
|
+
expect(queue).to receive(:bind).
|
63
|
+
with(exchange, :routing_key => "c")
|
64
|
+
|
65
|
+
expect(subject.queue).to eq queue
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Liebre::Runner::Starter::Resources do
|
4
|
+
|
5
|
+
let(:connection) { double 'connection' }
|
6
|
+
|
7
|
+
let(:pool_size) { 4 }
|
8
|
+
let(:config) { {"pool_size" => pool_size} }
|
9
|
+
|
10
|
+
subject { described_class.new(connection, config) }
|
11
|
+
|
12
|
+
describe '#exchange and #queue' do
|
13
|
+
let(:channel) { double 'channel' }
|
14
|
+
let(:exchange) { double 'exchange' }
|
15
|
+
|
16
|
+
let(:queue) { double 'queue' }
|
17
|
+
let(:queue_builder) { double 'queue_builder', :queue => queue, :exchange => exchange }
|
18
|
+
|
19
|
+
before do
|
20
|
+
allow(connection).to receive(:create_channel).
|
21
|
+
with(nil, pool_size).and_return(channel)
|
22
|
+
|
23
|
+
allow(channel).to receive(:default_exchange).
|
24
|
+
and_return(exchange)
|
25
|
+
|
26
|
+
allow(described_class::QueueBuilder).to receive(:new).
|
27
|
+
with(channel, config).and_return(queue_builder)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'builds exchange and queue properly' do
|
31
|
+
expect(subject.exchange).to eq exchange
|
32
|
+
expect(subject.queue ).to eq queue
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Liebre::Runner::Starter::RPC do
|
4
|
+
|
5
|
+
let(:connection) { double 'connection' }
|
6
|
+
|
7
|
+
let(:class_name) { "MyRPC" }
|
8
|
+
let(:pool_size) { 4 }
|
9
|
+
|
10
|
+
let :config do
|
11
|
+
{
|
12
|
+
"class_name" => class_name,
|
13
|
+
"pool_size" => pool_size,
|
14
|
+
"rpc" => true,
|
15
|
+
"exchange" => {
|
16
|
+
"name" => "test_exchange",
|
17
|
+
"type" => "direct",
|
18
|
+
"opts" => {
|
19
|
+
"durable" => false
|
20
|
+
}
|
21
|
+
},
|
22
|
+
"queue" => {
|
23
|
+
"name" => "test_queue",
|
24
|
+
"opts" => {
|
25
|
+
"durable" => false
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:exchange) { double 'exchange' }
|
32
|
+
let(:queue) { double 'queue' }
|
33
|
+
let(:channel) { double 'channel', :default_exchange => exchange }
|
34
|
+
let(:payload) { "the_payload" }
|
35
|
+
let(:response) { "the_response" }
|
36
|
+
|
37
|
+
subject { described_class.new(connection, config) }
|
38
|
+
|
39
|
+
let :resources do
|
40
|
+
double 'resources', :exchange => exchange, :queue => queue, :channel => channel
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:class_name) { "MyConsumer" }
|
44
|
+
|
45
|
+
let(:rpc_class) { double 'rpc_class', :name => 'rpc_class' }
|
46
|
+
let(:rpc_instance) { double 'rpc_instance' }
|
47
|
+
|
48
|
+
let(:reply_to) { "queue_to_reply_to" }
|
49
|
+
let(:correlation_id) { 123 }
|
50
|
+
let :meta do
|
51
|
+
double 'meta',
|
52
|
+
:reply_to => reply_to,
|
53
|
+
:correlation_id => correlation_id
|
54
|
+
end
|
55
|
+
|
56
|
+
let :opts do
|
57
|
+
{:routing_key => reply_to, :correlation_id => correlation_id}
|
58
|
+
end
|
59
|
+
|
60
|
+
let(:handler) { double 'handler' }
|
61
|
+
|
62
|
+
let(:deliver_info) { double 'deliver_info' }
|
63
|
+
|
64
|
+
before do
|
65
|
+
allow(Liebre::Runner::Starter::Resources).to receive(:new).
|
66
|
+
with(connection, config).and_return(resources)
|
67
|
+
|
68
|
+
stub_const(class_name, rpc_class)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'creates error queue and creates and subscribes to standard queue' do
|
72
|
+
|
73
|
+
expect(exchange).to receive(:publish).with(response, opts)
|
74
|
+
|
75
|
+
expect(queue).to receive :subscribe do |&block|
|
76
|
+
block.call(deliver_info, meta, payload)
|
77
|
+
end
|
78
|
+
|
79
|
+
expect(rpc_class).to receive :new do |given_payload, given_meta, callback|
|
80
|
+
expect(given_payload).to eq payload
|
81
|
+
expect(given_meta ).to eq meta
|
82
|
+
callback.call(response)
|
83
|
+
|
84
|
+
rpc_instance
|
85
|
+
end
|
86
|
+
|
87
|
+
expect(rpc_instance).to receive(:call)
|
88
|
+
|
89
|
+
subject.call
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|