liebre 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +51 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +47 -0
  5. data/LICENSE +22 -0
  6. data/README.md +268 -0
  7. data/lib/liebre.rb +24 -0
  8. data/lib/liebre/common.rb +7 -0
  9. data/lib/liebre/common/utils.rb +24 -0
  10. data/lib/liebre/config.rb +48 -0
  11. data/lib/liebre/connection_manager.rb +64 -0
  12. data/lib/liebre/publisher.rb +88 -0
  13. data/lib/liebre/runner.rb +59 -0
  14. data/lib/liebre/runner/consumers.rb +36 -0
  15. data/lib/liebre/runner/starter.rb +40 -0
  16. data/lib/liebre/runner/starter/consumer.rb +91 -0
  17. data/lib/liebre/runner/starter/consumer/handler.rb +35 -0
  18. data/lib/liebre/runner/starter/resources.rb +39 -0
  19. data/lib/liebre/runner/starter/resources/queue_builder.rb +58 -0
  20. data/lib/liebre/runner/starter/rpc.rb +45 -0
  21. data/lib/liebre/tasks.rb +12 -0
  22. data/lib/liebre/version.rb +5 -0
  23. data/liebre.gemspec +26 -0
  24. data/spec/config/liebre.yml +47 -0
  25. data/spec/config/rabbitmq.yml +35 -0
  26. data/spec/integration_spec.rb +73 -0
  27. data/spec/liebre/config_spec.rb +62 -0
  28. data/spec/liebre/connection_manager_spec.rb +40 -0
  29. data/spec/liebre/publisher_spec.rb +86 -0
  30. data/spec/liebre/runner/consumers_spec.rb +59 -0
  31. data/spec/liebre/runner/starter/consumer_spec.rb +140 -0
  32. data/spec/liebre/runner/starter/resources/queue_builder_spec.rb +69 -0
  33. data/spec/liebre/runner/starter/resources_spec.rb +36 -0
  34. data/spec/liebre/runner/starter/rpc_spec.rb +92 -0
  35. data/spec/liebre/runner/starter_spec.rb +59 -0
  36. data/spec/liebre/runner_spec.rb +50 -0
  37. data/spec/spec_helper.rb +23 -0
  38. 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