alchemy-flux 0.0.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.
- checksums.yaml +7 -0
- data/lib/alchemy-flux.rb +409 -0
- data/lib/alchemy-flux/flux_rack_handler.rb +159 -0
- data/spec/performance_spec.rb +64 -0
- data/spec/rack_handler_spec.rb +50 -0
- data/spec/resources_spec.rb +68 -0
- data/spec/service_spec.rb +448 -0
- data/spec/spec_helper.rb +7 -0
- metadata +183 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "performance of AlchemyFlux" do
|
4
|
+
|
5
|
+
after(:each) do
|
6
|
+
# This will stop EventMachine and disconnect RabbitMQ, reseting each test
|
7
|
+
AlchemyFlux::Service.stop
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should handle multiple messages at the same time' do
|
11
|
+
service_a = AlchemyFlux::Service.new("fluxa.service", {threadpool_size: 500}) do |message|
|
12
|
+
{'body' => "hola #{message['body']['name']}"}
|
13
|
+
end
|
14
|
+
|
15
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
16
|
+
|
17
|
+
service_a.start
|
18
|
+
service_b.start
|
19
|
+
|
20
|
+
calls = 400
|
21
|
+
|
22
|
+
responses = Queue.new
|
23
|
+
st = Time.now()
|
24
|
+
(1..calls).each do
|
25
|
+
service_b.send_message_to_service("fluxa.service", {'body' => {'name' => "Bob"}}) do |response|
|
26
|
+
responses << response
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
(1..calls).each do
|
31
|
+
resp = responses.pop
|
32
|
+
expect(resp['body']).to eq "hola Bob"
|
33
|
+
end
|
34
|
+
et = Time.now()
|
35
|
+
puts "Time for #{calls} async calls is #{(et-st)*1000}ms total; #{((et-st)*1000)/calls}ms per call"
|
36
|
+
service_a.stop
|
37
|
+
service_b.stop
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should handle multiple messages at the same time' do
|
41
|
+
service_a = AlchemyFlux::Service.new("fluxa.service", {threadpool_size: 500}) do |message|
|
42
|
+
{'body' => "hola #{message['body']['name']}"}
|
43
|
+
end
|
44
|
+
|
45
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
46
|
+
|
47
|
+
service_a.start
|
48
|
+
service_b.start
|
49
|
+
|
50
|
+
calls = 400
|
51
|
+
|
52
|
+
st = Time.now()
|
53
|
+
(1..calls).each do
|
54
|
+
resp = service_b.send_message_to_service("fluxa.service", {'body' => {'name' => "Bob"}})
|
55
|
+
expect(resp['body']).to eq "hola Bob"
|
56
|
+
end
|
57
|
+
|
58
|
+
et = Time.now()
|
59
|
+
puts "Time for #{calls} sync calls is #{(et-st)*1000}ms total; #{((et-st)*1000)/calls}ms per call"
|
60
|
+
service_a.stop
|
61
|
+
service_b.stop
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rack::Handler::AlchemyFlux do
|
4
|
+
|
5
|
+
after(:each) do
|
6
|
+
# This will stop EventMachine and disconnect RabbitMQ, reseting each test
|
7
|
+
AlchemyFlux::Service.stop
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#start" do
|
11
|
+
|
12
|
+
it 'should be able to start with a simple rack app' do
|
13
|
+
ENV['SERVICE_NAME'] = 'rack.service'
|
14
|
+
app = Proc.new do |env|
|
15
|
+
['200', {}, ['hi Bob']]
|
16
|
+
end
|
17
|
+
|
18
|
+
service_a = AlchemyFlux::Service.new("fluxa.service")
|
19
|
+
Rack::Handler::AlchemyFlux.start app
|
20
|
+
service_a.start
|
21
|
+
|
22
|
+
response = service_a.send_message_to_service("rack.service", {})
|
23
|
+
expect(response['body']).to eq "hi Bob"
|
24
|
+
service_a.stop
|
25
|
+
Rack::Handler::AlchemyFlux.stop
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should register resources with RESOURCE_PATHS env variable' do
|
29
|
+
ENV['SERVICE_NAME'] = 'rack.service'
|
30
|
+
ENV['RESOURCE_PATHS'] = '/alice,/bob'
|
31
|
+
app = Proc.new do |env|
|
32
|
+
['200', {}, ["hi #{env['PATH_INFO']}"]]
|
33
|
+
end
|
34
|
+
|
35
|
+
service_a = AlchemyFlux::Service.new("fluxa.service", :timeout => 100)
|
36
|
+
Rack::Handler::AlchemyFlux.start app
|
37
|
+
|
38
|
+
service_a.start
|
39
|
+
|
40
|
+
response = service_a.send_message_to_resource({'path' => '/alice'})
|
41
|
+
expect(response['body']).to eq "hi /alice"
|
42
|
+
|
43
|
+
response = service_a.send_message_to_resource({'path' => '/bob'})
|
44
|
+
expect(response['body']).to eq "hi /bob"
|
45
|
+
|
46
|
+
service_a.stop
|
47
|
+
Rack::Handler::AlchemyFlux.stop
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AlchemyFlux::Service do
|
4
|
+
|
5
|
+
after(:each) do
|
6
|
+
# This will stop EventMachine and disconnect RabbitMQ, reseting each test
|
7
|
+
AlchemyFlux::Service.stop
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#send_message_to_resource" do
|
11
|
+
|
12
|
+
it 'should be able to send messages to resource via path' do
|
13
|
+
resource_path = "/v1/fluxy_#{AlchemyFlux::Service.generateUUID()}"
|
14
|
+
service_a = AlchemyFlux::Service.new("fluxa.service", resource_paths: [resource_path]) do |message|
|
15
|
+
{'body' => "hi #{message['body']['name']}"}
|
16
|
+
end
|
17
|
+
|
18
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
19
|
+
|
20
|
+
service_a.start
|
21
|
+
service_b.start
|
22
|
+
|
23
|
+
response = service_b.send_message_to_resource({'path' => resource_path, 'body' => {'name' => "Bob"}})
|
24
|
+
expect(response['body']).to eq "hi Bob"
|
25
|
+
|
26
|
+
response = service_b.send_message_to_resource({'path' => "#{resource_path}/id", 'body' => {'name' => "Alice"}})
|
27
|
+
expect(response['body']).to eq "hi Alice"
|
28
|
+
service_a.stop
|
29
|
+
service_b.stop
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should be able to register multiple resources' do
|
33
|
+
resource_path1 = "/v1/fluxy_#{AlchemyFlux::Service.generateUUID()}"
|
34
|
+
resource_path2 = "/v1/fluxy_#{AlchemyFlux::Service.generateUUID()}"
|
35
|
+
service_a = AlchemyFlux::Service.new("fluxa.service", resource_paths: [resource_path1, resource_path2]) do |message|
|
36
|
+
{'body' => "hi #{message['body']['name']}"}
|
37
|
+
end
|
38
|
+
|
39
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
40
|
+
|
41
|
+
service_a.start
|
42
|
+
service_b.start
|
43
|
+
|
44
|
+
response = service_b.send_message_to_resource({'path' => resource_path1, 'body' => {'name' => "Bob"}})
|
45
|
+
expect(response['body']).to eq "hi Bob"
|
46
|
+
|
47
|
+
response = service_b.send_message_to_resource({'path' => resource_path2, 'body' => {'name' => "Alice"}})
|
48
|
+
expect(response['body']).to eq "hi Alice"
|
49
|
+
service_a.stop
|
50
|
+
service_b.stop
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
describe 'unhappy path' do
|
55
|
+
it 'should return error on a message to non existant service' do
|
56
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
57
|
+
|
58
|
+
service_b.start
|
59
|
+
|
60
|
+
expect(service_b.send_message_to_resource({'path' => '/v1/unregistered_resource'})).to eq AlchemyFlux::MessageNotDeliveredError
|
61
|
+
expect(service_b.transactions.length).to eq 0
|
62
|
+
|
63
|
+
service_b.stop
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,448 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AlchemyFlux::Service do
|
4
|
+
def thread_count
|
5
|
+
Thread.list.count
|
6
|
+
end
|
7
|
+
|
8
|
+
after(:each) do
|
9
|
+
# This will stop EventMachine and disconnect RabbitMQ, reseting each test
|
10
|
+
AlchemyFlux::Service.stop
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#initialize' do
|
14
|
+
it 'be initializable' do
|
15
|
+
AlchemyFlux::Service.new("test.service")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#Service.start' do
|
20
|
+
it 'should create the EM thread' do
|
21
|
+
init_thread_count = thread_count
|
22
|
+
AlchemyFlux::Service.start
|
23
|
+
expect(thread_count).to eq init_thread_count + 1
|
24
|
+
AlchemyFlux::Service.stop
|
25
|
+
expect(thread_count).to eq init_thread_count
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should raise an error if amqp uri is broken' do
|
29
|
+
expect{AlchemyFlux::Service.start('bad_uri')}.to raise_error(ArgumentError)
|
30
|
+
expect{AlchemyFlux::Service.start('amqp://localhosty')}.to raise_error(EventMachine::ConnectionError)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should start the Service connection on instance start' do
|
34
|
+
init_thread_count = thread_count
|
35
|
+
service = AlchemyFlux::Service.new("testflux.service")
|
36
|
+
service.start
|
37
|
+
expect(thread_count).to eq init_thread_count + 1
|
38
|
+
AlchemyFlux::Service.stop
|
39
|
+
expect(thread_count).to eq init_thread_count
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should raise an error if amqp uri is broken on instance start' do
|
43
|
+
service_bad_uri = AlchemyFlux::Service.new("testflux.service", ampq_uri: 'bad_uri')
|
44
|
+
service_bad_server = AlchemyFlux::Service.new("testflux.service", ampq_uri: 'amqp://localhosty')
|
45
|
+
expect{service_bad_uri.start}.to raise_error(ArgumentError)
|
46
|
+
expect{service_bad_server.start}.to raise_error(EventMachine::ConnectionError)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#start' do
|
51
|
+
|
52
|
+
it 'should start a service and increase thread count by 1' do
|
53
|
+
init_thread_count = thread_count
|
54
|
+
service = AlchemyFlux::Service.new("testflux.service")
|
55
|
+
expect(service.state).to eq :stopped
|
56
|
+
service.start
|
57
|
+
expect(thread_count).to eq init_thread_count + 1
|
58
|
+
expect(service.state).to eq :started
|
59
|
+
#stop should not decrease because EM might still be running
|
60
|
+
service.stop
|
61
|
+
expect(service.state).to eq :stopped
|
62
|
+
expect(thread_count).to eq init_thread_count + 1
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'start and stop multiple services with no extra threads' do
|
66
|
+
init_thread_count = thread_count
|
67
|
+
|
68
|
+
service_a = AlchemyFlux::Service.new("testfluxa.service")
|
69
|
+
service_b = AlchemyFlux::Service.new("testfluxb.service")
|
70
|
+
|
71
|
+
service_a.start
|
72
|
+
service_b.start
|
73
|
+
|
74
|
+
expect(thread_count).to eq init_thread_count + 1
|
75
|
+
|
76
|
+
service_a.stop
|
77
|
+
service_b.stop
|
78
|
+
|
79
|
+
expect(thread_count).to eq init_thread_count + 1
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should stop receiving messages after it has stopped' do
|
83
|
+
received_message = false
|
84
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
85
|
+
received_message = true
|
86
|
+
{}
|
87
|
+
end
|
88
|
+
|
89
|
+
service_b = AlchemyFlux::Service.new("fluxb.service", timeout: 100)
|
90
|
+
|
91
|
+
service_a.start
|
92
|
+
service_b.start
|
93
|
+
|
94
|
+
service_a.stop
|
95
|
+
expect(service_b.send_message_to_service("fluxa.service", {})).to eq AlchemyFlux::TimeoutError
|
96
|
+
service_b.stop
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should process incoming messages then stop' do
|
100
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
101
|
+
sleep(0.05)
|
102
|
+
{'body' => "hello"}
|
103
|
+
end
|
104
|
+
|
105
|
+
service_b = AlchemyFlux::Service.new("fluxb.service", timeout: 200)
|
106
|
+
|
107
|
+
service_a.start
|
108
|
+
service_b.start
|
109
|
+
|
110
|
+
response_queue = Queue.new
|
111
|
+
service_b.send_message_to_service("fluxa.service", {}) do |response|
|
112
|
+
response_queue << response
|
113
|
+
end
|
114
|
+
sleep(0.05)
|
115
|
+
service_a.stop
|
116
|
+
|
117
|
+
response = response_queue.pop
|
118
|
+
|
119
|
+
expect(response['body']).to eq "hello"
|
120
|
+
service_b.stop
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should process outgoing messages then stop' do
|
124
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
125
|
+
sleep(0.05)
|
126
|
+
{'body' => "hello"}
|
127
|
+
end
|
128
|
+
|
129
|
+
service_b = AlchemyFlux::Service.new("fluxb.service", timeout: 200)
|
130
|
+
|
131
|
+
service_a.start
|
132
|
+
service_b.start
|
133
|
+
|
134
|
+
response_queue = Queue.new
|
135
|
+
service_b.send_message_to_service("fluxa.service", {}) do |response|
|
136
|
+
response_queue << response
|
137
|
+
end
|
138
|
+
sleep(0.01)
|
139
|
+
service_b.stop
|
140
|
+
|
141
|
+
response = response_queue.pop
|
142
|
+
|
143
|
+
expect(response['body']).to eq "hello"
|
144
|
+
service_b.stop
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should stop receiving messages while stopping' do
|
148
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
149
|
+
sleep(0.8);
|
150
|
+
{'body' => "hello"}
|
151
|
+
end
|
152
|
+
|
153
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
154
|
+
|
155
|
+
service_a.start
|
156
|
+
service_b.start
|
157
|
+
|
158
|
+
response_queue = Queue.new
|
159
|
+
service_b.send_message_to_service("fluxa.service", {}) do |response|
|
160
|
+
response_queue << response
|
161
|
+
end
|
162
|
+
sleep(0.1)
|
163
|
+
Thread.new do service_a.stop end
|
164
|
+
sleep(0.3)
|
165
|
+
expect(service_b.send_message_to_service("fluxa.service", {})).to eq AlchemyFlux::TimeoutError
|
166
|
+
|
167
|
+
response = response_queue.pop
|
168
|
+
|
169
|
+
expect(response['body']).to eq "hello"
|
170
|
+
service_b.stop
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should have default service function' do
|
174
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
175
|
+
{'body' => "hi #{message['body']['name']}"}
|
176
|
+
end
|
177
|
+
|
178
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
179
|
+
|
180
|
+
service_a.start
|
181
|
+
service_b.start
|
182
|
+
|
183
|
+
response = service_b.send_message_to_service("fluxa.service", {'body' => {'name' => "Bob"}})
|
184
|
+
expect(response['body']).to eq "hi Bob"
|
185
|
+
|
186
|
+
response = service_a.send_message_to_service("fluxb.service", {'body' => {'name' => "Bob"}})
|
187
|
+
expect(response['body']).to be_empty
|
188
|
+
|
189
|
+
|
190
|
+
service_a.stop
|
191
|
+
service_b.stop
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
describe "#send_message_to_service" do
|
197
|
+
|
198
|
+
it 'should send and receive messages between services' do
|
199
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
200
|
+
{'body' => "hi #{message['body']['name']}"}
|
201
|
+
end
|
202
|
+
|
203
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
204
|
+
|
205
|
+
service_a.start
|
206
|
+
service_b.start
|
207
|
+
|
208
|
+
response = service_b.send_message_to_service("fluxa.service", {'body' => {'name' => "Bob"}})
|
209
|
+
expect(response['body']).to eq "hi Bob"
|
210
|
+
service_a.stop
|
211
|
+
service_b.stop
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
it 'can send and receive messages JSON messages' do
|
216
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
217
|
+
body = JSON.parse(message['body'])
|
218
|
+
{'body' => "hi #{body['name']}"}
|
219
|
+
end
|
220
|
+
|
221
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
222
|
+
|
223
|
+
service_a.start
|
224
|
+
service_b.start
|
225
|
+
|
226
|
+
response = service_b.send_message_to_service("fluxa.service", {'body' => '{"name" : "Bob"}'})
|
227
|
+
expect(response['body']).to eq "hi Bob"
|
228
|
+
service_a.stop
|
229
|
+
service_b.stop
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'should be able to send messages within the service call' do
|
233
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
234
|
+
resp = service_a.send_message_to_service("fluxb.service", {})
|
235
|
+
{'body' => "hi #{resp['body']}"}
|
236
|
+
end
|
237
|
+
|
238
|
+
service_b = AlchemyFlux::Service.new("fluxb.service") do |message|
|
239
|
+
{'body' => 'Bob'}
|
240
|
+
end
|
241
|
+
|
242
|
+
service_a.start
|
243
|
+
service_b.start
|
244
|
+
|
245
|
+
response = service_b.send_message_to_service("fluxa.service", {})
|
246
|
+
expect(response['body']).to eq "hi Bob"
|
247
|
+
service_a.stop
|
248
|
+
service_b.stop
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'should be able to send messages to itself' do
|
252
|
+
first = true
|
253
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
254
|
+
if first
|
255
|
+
first = !first
|
256
|
+
resp = service_a.send_message_to_service("fluxa.service", {})
|
257
|
+
{'body' => "hi #{resp['body']}"}
|
258
|
+
else
|
259
|
+
{'body' => 'Bob'}
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
264
|
+
|
265
|
+
service_a.start
|
266
|
+
service_b.start
|
267
|
+
|
268
|
+
response = service_b.send_message_to_service("fluxa.service", {})
|
269
|
+
expect(response['body']).to eq "hi Bob"
|
270
|
+
service_a.stop
|
271
|
+
service_b.stop
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'should generate transaction id if none is given' do
|
275
|
+
interaction_id = nil
|
276
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
277
|
+
expect(message['headers']).to have_key 'x-interaction-id'
|
278
|
+
expect(message['headers']['x-interaction-id']).not_to be_nil
|
279
|
+
interaction_id = message['headers']['x-interaction-id']
|
280
|
+
{ 'body' => "here" }
|
281
|
+
end
|
282
|
+
|
283
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
284
|
+
|
285
|
+
service_a.start
|
286
|
+
service_b.start
|
287
|
+
|
288
|
+
response = service_b.send_message_to_service("fluxa.service", {})
|
289
|
+
expect(response['body']).to eq "here"
|
290
|
+
expect(response['headers']).to have_key 'x-interaction-id'
|
291
|
+
expect(response['headers']['x-interaction-id']).not_to be_nil
|
292
|
+
expect(response['headers']['x-interaction-id']).to eq interaction_id
|
293
|
+
service_a.stop
|
294
|
+
service_b.stop
|
295
|
+
end
|
296
|
+
|
297
|
+
it 'should use given transaction id if one is provided' do
|
298
|
+
interaction_id = 'a123'
|
299
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
300
|
+
expect(message['headers']['x-interaction-id']).to eq interaction_id
|
301
|
+
{ 'body' => "here" }
|
302
|
+
end
|
303
|
+
|
304
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
305
|
+
|
306
|
+
service_a.start
|
307
|
+
service_b.start
|
308
|
+
|
309
|
+
response = service_b.send_message_to_service("fluxa.service", {
|
310
|
+
'headers' => {'x-interaction-id' => interaction_id}
|
311
|
+
})
|
312
|
+
expect(response['body']).to eq "here"
|
313
|
+
expect(response['headers']['x-interaction-id']).to eq interaction_id
|
314
|
+
service_a.stop
|
315
|
+
service_b.stop
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'should add to transactions and processing messages, and remove once complete' do
|
319
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
320
|
+
sleep(0.1)
|
321
|
+
{'body' => 'here'}
|
322
|
+
end
|
323
|
+
|
324
|
+
service_b = AlchemyFlux::Service.new("fluxb.service", timeout: 200)
|
325
|
+
|
326
|
+
service_a.start
|
327
|
+
service_b.start
|
328
|
+
|
329
|
+
expect(service_b.transactions.length).to eq 0
|
330
|
+
expect(service_a.processing_messages).to eq 0
|
331
|
+
|
332
|
+
response = Queue.new
|
333
|
+
service_b.send_message_to_service("fluxa.service", {}) do |resp|
|
334
|
+
response << resp
|
335
|
+
end
|
336
|
+
sleep(0.05)
|
337
|
+
expect(service_b.transactions.length).to eq 1
|
338
|
+
expect(service_a.processing_messages).to eq 1
|
339
|
+
|
340
|
+
expect(response.pop['body']).to eq 'here'
|
341
|
+
expect(service_b.transactions.length).to eq 0
|
342
|
+
expect(service_a.processing_messages).to eq 0
|
343
|
+
|
344
|
+
service_a.stop
|
345
|
+
service_b.stop
|
346
|
+
end
|
347
|
+
|
348
|
+
|
349
|
+
it 'should send and receive messages between services asynchronously' do
|
350
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
351
|
+
{'body' => "hola #{message['body']['name']}"}
|
352
|
+
end
|
353
|
+
|
354
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
355
|
+
|
356
|
+
service_a.start
|
357
|
+
service_b.start
|
358
|
+
|
359
|
+
block = Queue.new
|
360
|
+
service_b.send_message_to_service("fluxa.service", {'body' => {'name' => "Bob"}}) do |response|
|
361
|
+
block << response
|
362
|
+
end
|
363
|
+
|
364
|
+
response = block.pop
|
365
|
+
expect(response['body']).to eq "hola Bob"
|
366
|
+
|
367
|
+
service_a.stop
|
368
|
+
service_b.stop
|
369
|
+
end
|
370
|
+
|
371
|
+
describe 'unhappy path' do
|
372
|
+
it 'should be able to be nacked by the service_fn' do
|
373
|
+
called = 0
|
374
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
375
|
+
called += 1
|
376
|
+
raise AlchemyFlux::NAckError if called == 1
|
377
|
+
{ 'body' => "hola #{message['body']['name']}"}
|
378
|
+
end
|
379
|
+
|
380
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
381
|
+
|
382
|
+
service_a.start
|
383
|
+
service_b.start
|
384
|
+
|
385
|
+
block = Queue.new
|
386
|
+
service_b.send_message_to_service("fluxa.service", {'body' => {'name' => "Bob"}}) do |response|
|
387
|
+
block << response
|
388
|
+
end
|
389
|
+
response = block.pop
|
390
|
+
expect(response['body']).to eq "hola Bob"
|
391
|
+
expect(called).to eq 2
|
392
|
+
service_a.stop
|
393
|
+
service_b.stop
|
394
|
+
end
|
395
|
+
|
396
|
+
it 'should timeout if a message takes too long' do
|
397
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
398
|
+
sleep(0.1)
|
399
|
+
{}
|
400
|
+
end
|
401
|
+
|
402
|
+
service_b = AlchemyFlux::Service.new("fluxb.service", timeout: 100)
|
403
|
+
|
404
|
+
service_a.start
|
405
|
+
service_b.start
|
406
|
+
|
407
|
+
response = service_b.send_message_to_service("fluxa.service", {'body' => {'name' => "Bob"}})
|
408
|
+
|
409
|
+
expect(response).to eq AlchemyFlux::TimeoutError
|
410
|
+
expect(service_b.transactions.length).to eq 0
|
411
|
+
|
412
|
+
service_a.stop
|
413
|
+
service_b.stop
|
414
|
+
end
|
415
|
+
|
416
|
+
it 'should 500 if service_fn raises an error' do
|
417
|
+
service_a = AlchemyFlux::Service.new("fluxa.service") do |message|
|
418
|
+
raise Error.new
|
419
|
+
end
|
420
|
+
|
421
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
422
|
+
|
423
|
+
service_a.start
|
424
|
+
service_b.start
|
425
|
+
|
426
|
+
response = service_b.send_message_to_service("fluxa.service", {'body' => {'name' => "Bob"}})
|
427
|
+
|
428
|
+
expect(response['status_code']).to eq 500
|
429
|
+
expect(service_b.transactions.length).to eq 0
|
430
|
+
|
431
|
+
service_a.stop
|
432
|
+
service_b.stop
|
433
|
+
end
|
434
|
+
|
435
|
+
it 'should return error on a message to non existant service' do
|
436
|
+
service_b = AlchemyFlux::Service.new("fluxb.service")
|
437
|
+
|
438
|
+
service_b.start
|
439
|
+
|
440
|
+
expect(service_b.send_message_to_service("not_a_servoces.service", {})).to eq AlchemyFlux::MessageNotDeliveredError
|
441
|
+
expect(service_b.transactions.length).to eq 0
|
442
|
+
|
443
|
+
service_b.stop
|
444
|
+
end
|
445
|
+
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|