liebre 0.1.21 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/Gemfile.lock +9 -7
  4. data/{LICENSE → LICENSE.txt} +1 -1
  5. data/README.md +492 -195
  6. data/Rakefile +2 -0
  7. data/lib/liebre.rb +27 -16
  8. data/lib/liebre/actor.rb +11 -0
  9. data/lib/liebre/actor/consumer.rb +80 -0
  10. data/lib/liebre/actor/consumer/callback.rb +34 -0
  11. data/lib/liebre/actor/consumer/core.rb +80 -0
  12. data/lib/liebre/actor/consumer/reporter.rb +84 -0
  13. data/lib/liebre/actor/consumer/resources.rb +47 -0
  14. data/lib/liebre/actor/consumer/resources/config.rb +65 -0
  15. data/lib/liebre/actor/context.rb +40 -0
  16. data/lib/liebre/actor/context/declare.rb +44 -0
  17. data/lib/liebre/actor/context/handler.rb +44 -0
  18. data/lib/liebre/actor/publisher.rb +58 -0
  19. data/lib/liebre/actor/publisher/core.rb +42 -0
  20. data/lib/liebre/actor/publisher/reporter.rb +55 -0
  21. data/lib/liebre/actor/publisher/resources.rb +33 -0
  22. data/lib/liebre/actor/rpc/client.rb +88 -0
  23. data/lib/liebre/actor/rpc/client/core.rb +75 -0
  24. data/lib/liebre/actor/rpc/client/pending.rb +65 -0
  25. data/lib/liebre/actor/rpc/client/reporter.rb +71 -0
  26. data/lib/liebre/actor/rpc/client/resources.rb +62 -0
  27. data/lib/liebre/actor/rpc/client/task.rb +33 -0
  28. data/lib/liebre/actor/rpc/server.rb +74 -0
  29. data/lib/liebre/actor/rpc/server/callback.rb +28 -0
  30. data/lib/liebre/actor/rpc/server/core.rb +75 -0
  31. data/lib/liebre/actor/rpc/server/reporter.rb +72 -0
  32. data/lib/liebre/actor/rpc/server/resources.rb +53 -0
  33. data/lib/liebre/adapter.rb +8 -0
  34. data/lib/liebre/adapter/bunny.rb +23 -0
  35. data/lib/liebre/adapter/bunny/chan.rb +38 -0
  36. data/lib/liebre/adapter/bunny/conn.rb +32 -0
  37. data/lib/liebre/adapter/bunny/exchange.rb +20 -0
  38. data/lib/liebre/adapter/bunny/queue.rb +59 -0
  39. data/lib/liebre/adapter/interface.rb +26 -0
  40. data/lib/liebre/adapter/interface/chan.rb +29 -0
  41. data/lib/liebre/adapter/interface/conn.rb +21 -0
  42. data/lib/liebre/adapter/interface/exchange.rb +13 -0
  43. data/lib/liebre/adapter/interface/queue.rb +37 -0
  44. data/lib/liebre/bridge.rb +72 -0
  45. data/lib/liebre/bridge/channel_builder.rb +36 -0
  46. data/lib/liebre/config.rb +8 -38
  47. data/lib/liebre/engine.rb +61 -0
  48. data/lib/liebre/engine/builder.rb +48 -0
  49. data/lib/liebre/engine/repository.rb +56 -0
  50. data/lib/liebre/engine/state.rb +49 -0
  51. data/lib/liebre/runner.rb +15 -47
  52. data/lib/liebre/version.rb +1 -1
  53. data/liebre.gemspec +9 -7
  54. data/spec/integration/publish_and_consume_spec.rb +71 -0
  55. data/spec/integration/rpc_communication_spec.rb +81 -0
  56. data/spec/integration/start_twice_spec.rb +63 -0
  57. data/spec/liebre/actor/consumer_spec.rb +169 -0
  58. data/spec/liebre/actor/context/declare_spec.rb +69 -0
  59. data/spec/liebre/actor/context/handler_spec.rb +65 -0
  60. data/spec/liebre/actor/publisher_spec.rb +58 -0
  61. data/spec/liebre/actor/rpc/client_spec.rb +126 -0
  62. data/spec/liebre/actor/rpc/server_spec.rb +141 -0
  63. data/spec/liebre/adapter/bunny_spec.rb +66 -0
  64. data/spec/liebre/bridge_spec.rb +54 -0
  65. data/spec/liebre/engine/builder_spec.rb +42 -0
  66. data/spec/liebre/engine_spec.rb +90 -0
  67. data/spec/liebre/version_spec.rb +10 -0
  68. data/spec/spec_helper.rb +2 -9
  69. metadata +97 -58
  70. data/lib/liebre/common.rb +0 -7
  71. data/lib/liebre/common/utils.rb +0 -37
  72. data/lib/liebre/connection_manager.rb +0 -85
  73. data/lib/liebre/publisher.rb +0 -113
  74. data/lib/liebre/runner/consumers.rb +0 -46
  75. data/lib/liebre/runner/starter.rb +0 -44
  76. data/lib/liebre/runner/starter/consumer.rb +0 -129
  77. data/lib/liebre/runner/starter/consumer/handler.rb +0 -35
  78. data/lib/liebre/runner/starter/resources.rb +0 -45
  79. data/lib/liebre/runner/starter/resources/queue_builder.rb +0 -63
  80. data/lib/liebre/runner/starter/rpc.rb +0 -59
  81. data/lib/liebre/tasks.rb +0 -12
  82. data/spec/config/liebre.yml +0 -48
  83. data/spec/config/rabbitmq.yml +0 -35
  84. data/spec/integration_spec.rb +0 -76
  85. data/spec/liebre/config_spec.rb +0 -63
  86. data/spec/liebre/connection_manager_spec.rb +0 -44
  87. data/spec/liebre/publisher_spec.rb +0 -92
  88. data/spec/liebre/runner/consumers_spec.rb +0 -59
  89. data/spec/liebre/runner/starter/consumer_spec.rb +0 -145
  90. data/spec/liebre/runner/starter/resources/queue_builder_spec.rb +0 -69
  91. data/spec/liebre/runner/starter/resources_spec.rb +0 -38
  92. data/spec/liebre/runner/starter/rpc_spec.rb +0 -100
  93. data/spec/liebre/runner/starter_spec.rb +0 -70
  94. data/spec/liebre/runner_spec.rb +0 -54
@@ -0,0 +1,81 @@
1
+ RSpec.describe "RPC client-server communication" do
2
+
3
+ let(:connections) { {"test_conn" => {}} }
4
+
5
+ let :exchange do
6
+ {:name => "__test__.liebre.rpc_communication_exchange",
7
+ :type => "fanout",
8
+ :opts => {:auto_delete => true, :durable => false}}
9
+ end
10
+
11
+ let :client_queue do
12
+ {:prefix => "__test__.liebre.client_rpc_communication_queue"}
13
+ end
14
+
15
+ let :server_queue do
16
+ {:name => "__test__.liebre.server_rpc_communication_queue",
17
+ :opts => {:auto_delete => true, :durable => false}}
18
+ end
19
+
20
+ let(:handler_class) { double 'handler_class' }
21
+ let(:handler) { double 'handler' }
22
+
23
+ let :actors do
24
+ {
25
+ :rpc_clients => {
26
+ :my_client => {
27
+ :connection => "test_conn",
28
+ :resources => {:exchange => exchange, :queue => client_queue}
29
+ }
30
+ },
31
+ :rpc_servers => {
32
+ :my_server => {
33
+ :connection => "test_conn",
34
+ :prefetch_count => 5,
35
+ :pool_size => 1,
36
+ :handler => handler_class,
37
+ :resources => {:exchange => exchange, :queue => server_queue}
38
+ }
39
+ }
40
+ }
41
+ end
42
+
43
+ let :config do
44
+ Liebre::Config.new.tap do |config|
45
+ config.adapter = Liebre::Adapter::Bunny
46
+ config.connections = connections
47
+ config.actors = actors
48
+ end
49
+ end
50
+
51
+ let(:payload) { "some_data" }
52
+ let(:headers) { {"foo" => "bar"} }
53
+
54
+ let(:response) { "some_response" }
55
+
56
+ it "sends and receives data" do
57
+ engine = Liebre::Engine.new(config)
58
+ engine.start
59
+
60
+ repo = engine.repo
61
+ rpc_client = repo.rpc_client(:my_client)
62
+
63
+ callback = nil
64
+ expect(handler_class).to receive :new do |payload, meta, given_callback|
65
+ expect(payload ).to eq payload
66
+ expect(meta.headers).to eq headers
67
+ callback = given_callback
68
+
69
+ handler
70
+ end
71
+ expect(handler).to receive :call do
72
+ callback.reply(response)
73
+ end
74
+
75
+ sleep(0.1) # wait for all declarations and bindings to take place
76
+
77
+ opts = {:headers => headers}
78
+ expect(rpc_client.request(payload, opts, 0.2)).to eq response
79
+ end
80
+
81
+ end
@@ -0,0 +1,63 @@
1
+ RSpec.describe "Start actors twice" do
2
+
3
+ let(:connections) { {"test_conn" => {}} }
4
+
5
+ let :exchange do
6
+ {:name => "__test__.liebre.publish_and_consume_exchange",
7
+ :type => "fanout",
8
+ :opts => {:auto_delete => true, :durable => false}}
9
+ end
10
+
11
+ let :queue do
12
+ {:name => "__test__.liebre.publish_and_consume_queue",
13
+ :opts => {:auto_delete => true, :durable => false}}
14
+ end
15
+
16
+ let(:handler_class) { double 'handler_class' }
17
+ let(:handler) { double 'handler' }
18
+
19
+ let :actors do
20
+ {
21
+ :publishers => {
22
+ :my_publisher => {
23
+ :connection => "test_conn",
24
+ :resources => {:exchange => exchange}
25
+ }
26
+ },
27
+ :consumers => {
28
+ :my_consumer => {
29
+ :connection => "test_conn",
30
+ :prefetch_count => 5,
31
+ :pool_size => 1,
32
+ :handler => handler_class,
33
+ :resources => {:exchange => exchange, :queue => queue}
34
+ }
35
+ }
36
+ }
37
+ end
38
+
39
+ let :config do
40
+ Liebre::Config.new.tap do |config|
41
+ config.adapter = Liebre::Adapter::Bunny
42
+ config.connections = connections
43
+ config.actors = actors
44
+ end
45
+ end
46
+
47
+ let(:payload) { "some_data" }
48
+ let(:headers) { {"foo" => "bar"} }
49
+
50
+ it "sends and receives data" do
51
+ engine = Liebre::Engine.new(config)
52
+ repo = engine.repo
53
+
54
+ engine.start(only: [:publishers, :rpc_servers])
55
+ expect(repo.publisher(:my_publisher)).not_to be nil
56
+ expect { repo.consumer(:my_consumer) }.to raise_error KeyError
57
+
58
+ engine.start()
59
+ expect(repo.publisher(:my_publisher)).not_to be nil
60
+ expect(repo.consumer(:my_consumer) ).not_to be nil
61
+ end
62
+
63
+ end
@@ -0,0 +1,169 @@
1
+ RSpec.describe Liebre::Actor::Consumer do
2
+
3
+ let(:chan) { double 'chan' }
4
+ let(:declare) { double 'declare' }
5
+ let(:handler) { double 'handler' }
6
+
7
+ let :spec do
8
+ {:exchange => {:name => "foo"},
9
+ :queue => {:name => "bar"},
10
+ :bind => {:fake => "bind_config"}}
11
+ end
12
+
13
+ let(:logger) { double 'logger', :info => nil, :error => nil }
14
+
15
+ let :context do
16
+ double 'context', :chan => chan,
17
+ :declare => declare,
18
+ :name => "foo",
19
+ :handler => handler,
20
+ :spec => spec,
21
+ :logger => logger
22
+ end
23
+
24
+ subject { described_class.new(context) }
25
+
26
+ let(:queue) { double 'queue' }
27
+ let(:exchange) { double 'exchange' }
28
+
29
+ let(:dead_queue) { double 'dead_queue' }
30
+ let(:dead_exchange) { double 'dead_exchange' }
31
+
32
+ let(:dead_letter_opts) do
33
+ {:arguments => {"x-dead-letter-exchange" => "bar-error"}}
34
+ end
35
+
36
+ before do
37
+ allow(subject).to receive(:async).and_return(subject)
38
+
39
+ allow(declare).to receive(:queue).
40
+ with(:name => "bar", :opts => dead_letter_opts).and_return(queue)
41
+
42
+ allow(declare).to receive(:exchange).
43
+ with(:name => "foo").and_return(exchange)
44
+
45
+ allow(declare).to receive(:queue).
46
+ with(:name => "bar-error", :opts => {}).and_return(dead_queue)
47
+
48
+ allow(declare).to receive(:exchange).
49
+ with(:name => "bar-error", :type => "fanout", :opts => {}).and_return(dead_exchange)
50
+
51
+ allow(declare).to receive(:bind).
52
+ with(queue, exchange, :fake => "bind_config")
53
+
54
+ allow(declare).to receive(:bind).
55
+ with(dead_queue, dead_exchange)
56
+ end
57
+
58
+ let(:info) { double 'info' }
59
+ let(:meta) { double 'meta' }
60
+ let(:payload) { "some_data" }
61
+
62
+ describe '#start' do
63
+ it 'declares and binds queue and exchange, and subscribes to the queue' do
64
+ expect(declare).to receive(:queue).
65
+ with(:name => "bar", :opts => dead_letter_opts).and_return(queue)
66
+
67
+ expect(declare).to receive(:exchange).
68
+ with(:name => "foo").and_return(exchange)
69
+
70
+ expect(declare).to receive(:bind).
71
+ with(queue, exchange, :fake => "bind_config")
72
+
73
+ expect(declare).to receive(:queue).
74
+ with(:name => "bar-error", :opts => {}).and_return(dead_queue)
75
+
76
+ expect(declare).to receive(:exchange).
77
+ with(:name => "bar-error", :type => "fanout", :opts => {}).and_return(dead_exchange)
78
+
79
+ expect(declare).to receive(:bind).
80
+ with(dead_queue, dead_exchange)
81
+
82
+ subscription_block = nil
83
+ expect(queue).to receive(:subscribe) do |opts, &block|
84
+ expect(opts).to eq :block => false, :manual_ack => true
85
+ subscription_block = block
86
+ end
87
+
88
+ subject.start
89
+
90
+ expect(subject).to receive(:consume).
91
+ with(info, meta, payload)
92
+
93
+ subscription_block.(info, meta, payload)
94
+ end
95
+ end
96
+
97
+ describe '#clean' do
98
+ it 'deletes all queues and exchanges' do
99
+ expect(queue ).to receive(:delete)
100
+ expect(exchange ).to receive(:delete)
101
+ expect(dead_queue ).to receive(:delete)
102
+ expect(dead_exchange).to receive(:delete)
103
+
104
+ subject.clean
105
+ end
106
+ end
107
+
108
+ describe '#consume' do
109
+ context 'on success' do
110
+ it 'runs the handler with a callbacks object' do
111
+ callback = nil
112
+ expect(handler).to receive :call do |given_payload, given_meta, given_callback|
113
+ expect(given_payload).to eq payload
114
+ expect(given_meta ).to eq meta
115
+
116
+ callback = given_callback
117
+ end
118
+
119
+ subject.consume(info, meta, payload)
120
+
121
+ expect(subject).to receive(:ack).with(info, {})
122
+ callback.ack()
123
+
124
+ expect(subject).to receive(:nack).with(info, {})
125
+ callback.nack()
126
+
127
+ expect(subject).to receive(:reject).with(info, :requeue => true)
128
+ callback.reject(:requeue => true)
129
+ end
130
+ end
131
+
132
+ context 'on handler failure' do
133
+ let(:error) { double 'error' }
134
+
135
+ it 'calls failed on the consumer' do
136
+ error_block = nil
137
+ expect(handler).to receive :call do |payload, meta, callback, &block|
138
+ error_block = block
139
+ end
140
+
141
+ subject.consume(info, meta, payload)
142
+
143
+ expect(subject).to receive(:failed).
144
+ with(info, error)
145
+
146
+ error_block.(error)
147
+ end
148
+ end
149
+ end
150
+
151
+ describe '#ack, #nack, #reject and #failed' do
152
+ let(:error) { double 'error', :message => "foo", :backtrace => [] }
153
+
154
+ it 'delegates to the queue' do
155
+ expect(queue).to receive(:ack).with(info, {})
156
+ subject.ack(info)
157
+
158
+ expect(queue).to receive(:nack).with(info, {})
159
+ subject.nack(info)
160
+
161
+ expect(queue).to receive(:reject).with(info, :requeue => true)
162
+ subject.reject(info, :requeue => true)
163
+
164
+ expect(queue).to receive(:reject).with(info, {})
165
+ subject.failed(info, error)
166
+ end
167
+ end
168
+
169
+ end
@@ -0,0 +1,69 @@
1
+ RSpec.describe Liebre::Actor::Context::Declare do
2
+
3
+ let(:chan) { double 'chan' }
4
+
5
+ subject { described_class.new(chan) }
6
+
7
+ describe '#default_exchange' do
8
+ let(:default_exchange) { double 'default_exchange' }
9
+
10
+ it 'builds the default exchange' do
11
+ expect(chan).to receive(:default_exchange).
12
+ and_return(default_exchange)
13
+
14
+ expect(subject.default_exchange).to eq default_exchange
15
+ end
16
+ end
17
+
18
+ describe '#exchange' do
19
+ let(:exchange) { double 'exchange' }
20
+
21
+ let :opts do
22
+ {:name => "foo",
23
+ :type => "fanout",
24
+ :opts => {:durable => true}}
25
+ end
26
+
27
+ it 'builds an exchange with the given options' do
28
+ expect(chan).to receive(:exchange).
29
+ with("foo", "fanout", :durable => true).
30
+ and_return(exchange)
31
+
32
+ expect(subject.exchange(opts)).to eq exchange
33
+ end
34
+ end
35
+
36
+ describe '#queue' do
37
+ let(:queue) { double 'queue' }
38
+
39
+ let :opts do
40
+ {:name => "foo",
41
+ :opts => {:durable => true}}
42
+ end
43
+
44
+ it 'builds an queue with the given options' do
45
+ expect(chan).to receive(:queue).
46
+ with("foo", :durable => true).
47
+ and_return(queue)
48
+
49
+ expect(subject.queue(opts)).to eq queue
50
+ end
51
+ end
52
+
53
+ describe '#bind' do
54
+ let(:queue) { double 'queue' }
55
+ let(:exchange) { double 'exchange' }
56
+ let(:opts) { [{:routing_key => "foo"}, {:routing_key => "bar"}] }
57
+
58
+ it 'binds as many option sets as given' do
59
+ expect(queue).to receive(:bind).
60
+ with(exchange, :routing_key => "foo")
61
+
62
+ expect(queue).to receive(:bind).
63
+ with(exchange, :routing_key => "bar")
64
+
65
+ subject.bind(queue, exchange, opts)
66
+ end
67
+ end
68
+
69
+ end
@@ -0,0 +1,65 @@
1
+ RSpec.describe Liebre::Actor::Context::Handler do
2
+
3
+ let(:pool_size) { 3 }
4
+ let(:handler_class) { double 'handler_class' }
5
+
6
+ let :opts do
7
+ {:pool_size => pool_size,
8
+ :handler => handler_class}
9
+ end
10
+
11
+ subject { described_class.new(opts) }
12
+
13
+ let(:pool) { double 'pool' }
14
+
15
+ before do
16
+ allow(Concurrent::FixedThreadPool).to receive(:new).
17
+ with(pool_size).and_return(pool)
18
+ end
19
+
20
+ describe '#call' do
21
+ def pool_block *args, &block
22
+ pool_block = nil
23
+ expect(pool).to receive :post do |&given_block|
24
+ pool_block = given_block
25
+ end
26
+
27
+ subject.call(*args, &block)
28
+ pool_block
29
+ end
30
+
31
+ let(:handler) { double 'handler' }
32
+
33
+ context 'on success' do
34
+ it 'runs the handler on the pool' do
35
+ block = pool_block("foo", "bar") {}
36
+
37
+ expect(handler_class).to receive(:new).
38
+ with("foo", "bar").and_return(handler)
39
+
40
+ expect(handler).to receive(:call)
41
+
42
+ block.()
43
+ end
44
+ end
45
+
46
+ context 'on handler error' do
47
+ let(:target) { double 'target' }
48
+
49
+ it 'runs the given block with the error as argument' do
50
+ block = pool_block("foo") { target.boom! }
51
+
52
+ expect(target).to receive(:boom!)
53
+
54
+ expect(handler_class).to receive(:new).
55
+ with("foo").and_return(handler)
56
+
57
+ expect(handler).to receive(:call).
58
+ and_raise("boom")
59
+
60
+ block.()
61
+ end
62
+ end
63
+ end
64
+
65
+ end