liebre 0.1.21 → 0.2.1

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.
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,58 @@
1
+ RSpec.describe Liebre::Actor::Publisher do
2
+
3
+ let(:chan) { double 'chan' }
4
+ let(:declare) { double 'declare' }
5
+ let(:spec) { {:exchange => {:fake => "config"}} }
6
+ let(:logger) { double 'logger', :info => nil, :error => nil }
7
+
8
+ let :context do
9
+ double 'context', :chan => chan,
10
+ :declare => declare,
11
+ :name => "foo",
12
+ :spec => spec,
13
+ :logger => logger
14
+ end
15
+
16
+ subject { described_class.new(context) }
17
+
18
+ before do
19
+ allow(subject).to receive(:async).and_return(subject)
20
+ end
21
+
22
+ let(:exchange) { double 'exchange' }
23
+
24
+ before do
25
+ allow(declare).to receive(:exchange).
26
+ with(:fake => "config").and_return(exchange)
27
+ end
28
+
29
+ describe '#start' do
30
+ it 'declares the exchange' do
31
+ expect(declare).to receive(:exchange).
32
+ with(:fake => "config").and_return(exchange)
33
+
34
+ subject.start
35
+ end
36
+ end
37
+
38
+ describe '#clean' do
39
+ it 'deletes the exchange' do
40
+ expect(exchange).to receive(:delete)
41
+
42
+ subject.clean
43
+ end
44
+ end
45
+
46
+ describe '#publish' do
47
+ it 'publishes through the exchange' do
48
+ allow(declare).to receive(:exchange).
49
+ with(:fake => "config").and_return(exchange)
50
+
51
+ expect(exchange).to receive(:publish).
52
+ with("some_data", :routing_key => "bar")
53
+
54
+ subject.publish("some_data", :routing_key => "bar")
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,126 @@
1
+ require 'concurrent'
2
+
3
+ RSpec.describe Liebre::Actor::RPC::Client do
4
+
5
+ let(:chan) { double 'chan' }
6
+ let(:declare) { double 'declare' }
7
+
8
+ let :spec do
9
+ {:exchange => {:fake => "exchange_config"},
10
+ :queue => {:prefix => "client_test"},
11
+ :bind => {:fake => "bind_config"}}
12
+ end
13
+
14
+ let(:logger) { double 'logger', :info => nil, :error => nil }
15
+
16
+ let :context do
17
+ double 'context', :chan => chan,
18
+ :declare => declare,
19
+ :name => "foo",
20
+ :spec => spec,
21
+ :logger => logger
22
+ end
23
+
24
+ subject { described_class.new(context) }
25
+
26
+ let(:response_queue) { double 'request_queue', :name => "queue_1234" }
27
+ let(:request_exchange) { double 'request_exchange' }
28
+ let(:task) { double 'task', :execute => true, :shutdown => true }
29
+
30
+ before do
31
+ allow(subject).to receive(:async).and_return(subject)
32
+
33
+ allow(declare).to receive :queue do |config|
34
+ expect(config[:name]).to match /^client_test_.+$/
35
+ expect(config[:opts]).to eq :auto_delete => true, :exclusive => true, :durable => false
36
+
37
+ response_queue
38
+ end
39
+
40
+ allow(declare).to receive(:exchange).
41
+ with(:fake => "exchange_config").and_return(request_exchange)
42
+
43
+ allow(Concurrent::TimerTask).to receive(:new).
44
+ with(anything).and_return(task)
45
+ end
46
+
47
+ let(:info) { double 'info' }
48
+ let(:meta) { double 'meta' }
49
+ let(:payload) { "some_payload" }
50
+ let(:response) { "some_response" }
51
+
52
+ describe '#start' do
53
+ it 'declares queue and exchange, and subscribes to the queue' do
54
+ expect(declare).to receive :queue do |config|
55
+ expect(config[:name]).to match /^client_test_.+$/
56
+ expect(config[:opts]).to eq :auto_delete => true, :exclusive => true, :durable => false
57
+
58
+ response_queue
59
+ end
60
+
61
+ expect(declare).to receive(:exchange).
62
+ with(:fake => "exchange_config").and_return(request_exchange)
63
+
64
+ subscription_block = nil
65
+ expect(response_queue).to receive(:subscribe) do |opts, &block|
66
+ expect(opts).to eq :block => false, :manual_ack => false
67
+ subscription_block = block
68
+ end
69
+
70
+ task_block = nil
71
+ expect(Concurrent::TimerTask).to receive(:new) do |opts, &block|
72
+ expect(opts[:execution_interval]).to be_a Numeric
73
+ task_block = block
74
+
75
+ task
76
+ end
77
+ expect(task).to receive(:execute)
78
+
79
+ subject.start
80
+
81
+ expect(subject).to receive(:reply).with(meta, response)
82
+ subscription_block.(info, meta, response)
83
+
84
+ expect(subject).to receive(:expire)
85
+ task_block.()
86
+ end
87
+ end
88
+
89
+ describe '#clean' do
90
+ it 'deletes queue and exchange' do
91
+ expect(response_queue ).to receive(:delete)
92
+ expect(request_exchange).to receive(:delete)
93
+
94
+ subject.clean
95
+ end
96
+ end
97
+
98
+ describe '#request and #reply' do
99
+ it 'replies and releases the client only when a matching response is received' do
100
+ correlation_id = nil
101
+ expect(request_exchange).to receive :publish do |given_payload, opts|
102
+ expect(payload ).to eq payload
103
+ expect(opts[:reply_to]).to eq "queue_1234"
104
+
105
+ correlation_id = opts[:correlation_id]
106
+ end
107
+
108
+ thread = Thread.new do
109
+ subject.request(payload)
110
+ end
111
+ sleep(0.1)
112
+ expect(thread.alive?).to eq true # waiting for response
113
+
114
+ no_matching_meta = double("not_matching_meta", :correlation_id => "not-matching")
115
+ subject.reply(no_matching_meta, response)
116
+ sleep(0.1)
117
+ expect(thread.alive?).to eq true # waiting for a matching response
118
+
119
+ matching_meta = double("matching_meta", :correlation_id => correlation_id)
120
+ subject.reply(matching_meta, response)
121
+ sleep(0.1)
122
+ expect(thread.value).to eq response
123
+ end
124
+ end
125
+
126
+ end
@@ -0,0 +1,141 @@
1
+ RSpec.describe Liebre::Actor::RPC::Server do
2
+
3
+ let(:chan) { double 'chan' }
4
+ let(:declare) { double 'declare' }
5
+ let(:handler) { double 'handler' }
6
+
7
+ let :spec do
8
+ {:exchange => {:fake => "exchange_config"},
9
+ :queue => {:fake => "queue_config"},
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(:request_queue) { double 'request_queue' }
27
+ let(:request_exchange) { double 'request_exchange' }
28
+ let(:response_exchange) { double 'response_exchange' }
29
+
30
+ before do
31
+ allow(subject).to receive(:async).and_return(subject)
32
+
33
+ allow(declare).to receive(:queue).
34
+ with(:fake => "queue_config").and_return(request_queue)
35
+
36
+ allow(declare).to receive(:exchange).
37
+ with(:fake => "exchange_config").and_return(request_exchange)
38
+
39
+ allow(declare).to receive(:default_exchange).
40
+ and_return(response_exchange)
41
+
42
+ allow(declare).to receive(:bind).
43
+ with(request_queue, request_exchange, :fake => "bind_config")
44
+ end
45
+
46
+ let(:info) { double 'info' }
47
+ let(:payload) { "some_data" }
48
+
49
+ let :meta do
50
+ double 'meta', :reply_to => "reply.queue",
51
+ :correlation_id => "123"
52
+ end
53
+
54
+ describe '#start' do
55
+ it 'declares and binds queue and exchange, and subscribes to the queue' do
56
+ expect(declare).to receive(:queue).
57
+ with(:fake => "queue_config").and_return(request_queue)
58
+
59
+ expect(declare).to receive(:exchange).
60
+ with(:fake => "exchange_config").and_return(request_exchange)
61
+
62
+ expect(declare).to receive(:default_exchange).
63
+ and_return(response_exchange)
64
+
65
+ expect(declare).to receive(:bind).
66
+ with(request_queue, request_exchange, :fake => "bind_config")
67
+
68
+ subscription_block = nil
69
+ expect(request_queue).to receive(:subscribe) do |opts, &block|
70
+ expect(opts).to eq :block => false, :manual_ack => false
71
+ subscription_block = block
72
+ end
73
+
74
+ subject.start
75
+
76
+ expect(subject).to receive(:handle).
77
+ with(meta, payload)
78
+
79
+ subscription_block.(info, meta, payload)
80
+ end
81
+ end
82
+
83
+ describe '#clean' do
84
+ it 'deletes queue and exchange' do
85
+ expect(request_queue ).to receive(:delete)
86
+ expect(response_exchange).to receive(:delete)
87
+
88
+ subject.clean
89
+ end
90
+ end
91
+
92
+ describe '#handle' do
93
+ context 'on success' do
94
+ let(:response) { "some_response" }
95
+
96
+ it 'runs the handler with a callback object' do
97
+ callback = nil
98
+ expect(handler).to receive :call do |given_payload, given_meta, given_callback|
99
+ expect(given_payload).to eq payload
100
+ expect(given_meta ).to eq meta
101
+
102
+ callback = given_callback
103
+ end
104
+
105
+ subject.handle(meta, payload)
106
+
107
+ expect(subject).to receive(:reply).with(meta, "some_response", {})
108
+ callback.reply(response)
109
+ end
110
+ end
111
+
112
+ context 'on handler failure' do
113
+ let(:error) { double 'error' }
114
+
115
+ it 'calls failed on the server' do
116
+ error_block = nil
117
+ expect(handler).to receive :call do |payload, meta, callback, &block|
118
+ error_block = block
119
+ end
120
+
121
+ subject.handle(meta, payload)
122
+
123
+ expect(subject).to receive(:failed).
124
+ with(meta, error)
125
+
126
+ error_block.(error)
127
+ end
128
+ end
129
+ end
130
+
131
+ describe '#reply' do
132
+ let(:response) { "some_response" }
133
+
134
+ it 'delegates to the queue' do
135
+ expect(response_exchange).to receive(:publish).
136
+ with(response, :routing_key => "reply.queue", :correlation_id => "123")
137
+ subject.reply(meta, response)
138
+ end
139
+ end
140
+
141
+ end
@@ -0,0 +1,66 @@
1
+ RSpec.describe Liebre::Adapter::Bunny do
2
+
3
+ subject { described_class.new }
4
+
5
+ describe '#connect and conn methods' do
6
+ let(:opts) { {:host => "localhost"} }
7
+
8
+ let(:common_opts) { {:auto_delete => true, :durable => false} }
9
+
10
+ it 'everything' do
11
+ # start a connection
12
+ #
13
+ conn = subject.connection(opts)
14
+ session = conn.session
15
+
16
+ expect(conn.opts ).to eq opts
17
+ expect(session.open?).to eq false
18
+
19
+ conn.start
20
+ expect(session.open?).to eq true
21
+
22
+ # open a channel
23
+ #
24
+ chan = conn.open_channel
25
+ channel = chan.channel
26
+ expect(channel.open?).to eq true
27
+
28
+ # open an exchange, a queue and bind them
29
+ #
30
+ exchange = chan.exchange("foo", "fanout", common_opts)
31
+ queue = chan.queue("bar", common_opts)
32
+ queue.bind(exchange)
33
+
34
+ # publish and get message, reject and ack
35
+ #
36
+ exchange.publish("some_data")
37
+
38
+ queue.get(:manual_ack => true) do |info, properties, payload|
39
+ expect(payload).to eq "some_data"
40
+
41
+ queue.reject(info, :requeue => true)
42
+ end
43
+
44
+ queue.get(:manual_ack => true) do |info, properties, payload|
45
+ expect(payload).to eq "some_data"
46
+
47
+ queue.ack(info, :requeue => true)
48
+ end
49
+
50
+ queue.get(:manual_ack => true) do |*args|
51
+ expect(args).to eq [nil, nil, nil]
52
+ end
53
+
54
+ # close a channel
55
+ #
56
+ chan.close
57
+ expect(channel.open?).to eq false
58
+
59
+ # stop a connection
60
+ #
61
+ conn.stop
62
+ expect(session.open?).to eq false
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,54 @@
1
+ RSpec.describe Liebre::Bridge do
2
+
3
+ let(:adapter) { double 'adapter' }
4
+
5
+ let(:name_1) { :foo }
6
+ let(:name_2) { :bar }
7
+ let(:opts_1) { double 'opts_1' }
8
+ let(:opts_2) { double 'opts_2' }
9
+
10
+ let(:connections) { {name_1 => opts_1, name_2 => opts_2}}
11
+
12
+ let(:logger) { double 'logger', :info => nil }
13
+
14
+ let :config do
15
+ double 'config', :adapter => adapter,
16
+ :connections => connections,
17
+ :logger => logger
18
+ end
19
+
20
+ subject { described_class.new(config) }
21
+
22
+ let(:conn_1) { double 'conn_1' }
23
+ let(:conn_2) { double 'conn_2' }
24
+
25
+ before do
26
+ allow(adapter).to receive(:connection).
27
+ with(opts_1).and_return(conn_1)
28
+
29
+ allow(adapter).to receive(:connection).
30
+ with(opts_2).and_return(conn_2)
31
+ end
32
+
33
+ describe '#open_channel' do
34
+ let(:chan) { double 'chan' }
35
+
36
+ let :chan_opts do
37
+ {:connection => name_2, :prefetch_count => 8}
38
+ end
39
+
40
+ it 'opens configured channels' do
41
+ expect(conn_1).to receive(:start)
42
+ expect(conn_2).to receive(:start)
43
+ subject.start
44
+
45
+ expect(conn_2).to receive(:open_channel).
46
+ and_return(chan)
47
+ expect(chan).to receive(:set_prefetch).
48
+ with(chan_opts[:prefetch_count])
49
+
50
+ expect(subject.open_channel(chan_opts)).to eq chan
51
+ end
52
+ end
53
+
54
+ end