combi 0.2.1 → 0.3.0
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 +4 -4
- data/lib/combi/buses/bus.rb +8 -15
- data/lib/combi/buses/http.rb +12 -8
- data/lib/combi/buses/in_process.rb +22 -12
- data/lib/combi/buses/queue.rb +30 -26
- data/lib/combi/buses/web_socket.rb +27 -23
- data/lib/combi/queue_service.rb +6 -5
- data/lib/combi/service.rb +1 -4
- data/lib/combi/version.rb +1 -1
- data/spec/lib/combi/buses/bus_spec.rb +2 -2
- data/spec/lib/combi/buses/queue_spec.rb +18 -0
- data/spec/lib/combi/buses/web_socket_spec.rb +17 -0
- data/spec/shared_examples/standard_bus.rb +205 -116
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8d52d86d25a8990c1034e0acfaadb4417164c07
|
4
|
+
data.tar.gz: 90ae51a9bf47ce6a2ff6fcfe13ea95fb076a8ba6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67235e10e87a924be9c053eead194bf0f6f30f47682a3c13a204d0f77d01354810841664116b2791ae2ade902103d0f9a1c2fe31ca8e6bf6771aa6c7b68b829e
|
7
|
+
data.tar.gz: 0d5f694d3db7fc22d18a01cc40d64474a296e4811bf40ac9084347e7c89ae17cc824165c3a7729cc0430a034d6a1e2bcf84aa7d91666bae54917d4f16caeb5ac
|
data/lib/combi/buses/bus.rb
CHANGED
@@ -21,9 +21,6 @@ module Combi
|
|
21
21
|
service_instance.actions.each do |service_name|
|
22
22
|
self.add_routes_for(service_name, service_instance)
|
23
23
|
end
|
24
|
-
service_instance.fast_actions.each do |service_name|
|
25
|
-
self.add_routes_for(service_name, service_instance, fast: true)
|
26
|
-
end
|
27
24
|
service_instance.setup(self, options[:context])
|
28
25
|
end
|
29
26
|
|
@@ -93,16 +90,16 @@ module Combi
|
|
93
90
|
service_class.new
|
94
91
|
end
|
95
92
|
|
96
|
-
def add_routes_for(service_name, service_instance
|
93
|
+
def add_routes_for(service_name, service_instance)
|
97
94
|
service_instance.remote_methods.each do |method|
|
98
|
-
add_route_for(service_name, method, service_instance
|
95
|
+
add_route_for(service_name, method, service_instance)
|
99
96
|
end
|
100
97
|
end
|
101
98
|
|
102
|
-
def add_route_for(service_name, action_name, service_instance
|
99
|
+
def add_route_for(service_name, action_name, service_instance)
|
103
100
|
path = [service_name, action_name].join('/')
|
104
101
|
puts "New route: #{path} :: #{service_instance}"
|
105
|
-
@routes[path] =
|
102
|
+
@routes[path] = service_instance
|
106
103
|
end
|
107
104
|
|
108
105
|
# Funny name of a exception used to signal that the requested
|
@@ -114,14 +111,10 @@ module Combi
|
|
114
111
|
|
115
112
|
def resolve_route(service_name, kind)
|
116
113
|
path = [service_name, kind].join('/')
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
log "[WARNING] Service Path #{path} not found"
|
122
|
-
log "[WARNING] routes: #{@routes.keys.inspect}"
|
123
|
-
raise UnknownStop.new(path)
|
124
|
-
end
|
114
|
+
return @routes[path] if @routes[path]
|
115
|
+
log "[WARNING] Service Path #{path} not found"
|
116
|
+
log "[WARNING] routes: #{@routes.keys.inspect}"
|
117
|
+
raise UnknownStop.new(path)
|
125
118
|
end
|
126
119
|
|
127
120
|
def invoke_service(service_name, action, params)
|
data/lib/combi/buses/http.rb
CHANGED
@@ -53,17 +53,21 @@ module Combi
|
|
53
53
|
def request(name, kind, message, options = {})
|
54
54
|
options[:timeout] ||= RPC_DEFAULT_TIMEOUT
|
55
55
|
|
56
|
-
correlation_id = Combi::Correlation.generate
|
57
|
-
waiter = @response_store.wait_for(correlation_id, options[:timeout])
|
58
56
|
url = "#{@options[:remote_api]}#{name}/#{kind}"
|
59
57
|
message_json = Yajl::Encoder.encode(message)
|
60
58
|
request_async = EventMachine::HttpRequest.new(url, connection_timeout: options[:timeout]).post(body: message_json)
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
59
|
+
if options[:fast]
|
60
|
+
waiter = nil
|
61
|
+
else
|
62
|
+
correlation_id = Combi::Correlation.generate
|
63
|
+
waiter = @response_store.wait_for(correlation_id, options[:timeout])
|
64
|
+
request_async.callback do |r|
|
65
|
+
parsed = Yajl::Parser.parse(r.response, symbolize_keys: true)
|
66
|
+
waiter.succeed(parsed)
|
67
|
+
end
|
68
|
+
request_async.errback do |x|
|
69
|
+
waiter.fail(Timeout::Error.new)
|
70
|
+
end
|
67
71
|
end
|
68
72
|
waiter
|
69
73
|
end
|
@@ -5,22 +5,32 @@ module Combi
|
|
5
5
|
|
6
6
|
def request(service_name, kind, message, options = {})
|
7
7
|
options[:timeout] ||= RPC_DEFAULT_TIMEOUT
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
response.callback do |service_response|
|
14
|
-
waiter.succeed service_response
|
8
|
+
message = Yajl::Parser.parse(Yajl::Encoder.encode(message), symbolize_keys: true)
|
9
|
+
if options[:fast]
|
10
|
+
operation = Proc.new do
|
11
|
+
Timeout.timeout(options[:timeout]) do
|
12
|
+
invoke_service(service_name, kind, message)
|
15
13
|
end
|
16
|
-
|
17
|
-
|
14
|
+
end
|
15
|
+
EM::defer operation
|
16
|
+
return nil
|
17
|
+
else
|
18
|
+
waiter = EventMachine::DefaultDeferrable.new
|
19
|
+
begin
|
20
|
+
Timeout.timeout(options[:timeout]) do
|
21
|
+
response = invoke_service(service_name, kind, message)
|
22
|
+
response.callback do |service_response|
|
23
|
+
waiter.succeed service_response
|
24
|
+
end
|
25
|
+
response.errback do |service_response|
|
26
|
+
waiter.fail error: service_response
|
27
|
+
end
|
18
28
|
end
|
29
|
+
rescue Timeout::Error => e
|
30
|
+
waiter.fail error: 'Timeout::Error'
|
19
31
|
end
|
20
|
-
|
21
|
-
waiter.fail error: 'Timeout::Error'
|
32
|
+
waiter
|
22
33
|
end
|
23
|
-
waiter
|
24
34
|
end
|
25
35
|
end
|
26
36
|
end
|
data/lib/combi/buses/queue.rb
CHANGED
@@ -25,57 +25,61 @@ module Combi
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
def add_routes_for(service_name, service_instance
|
29
|
-
create_queue_for_service(service_name
|
28
|
+
def add_routes_for(service_name, service_instance)
|
29
|
+
create_queue_for_service(service_name)
|
30
30
|
super
|
31
31
|
end
|
32
32
|
|
33
|
-
def create_queue_for_service(service_name
|
33
|
+
def create_queue_for_service(service_name)
|
34
34
|
log "creating queue #{service_name}"
|
35
35
|
queue_options = {}
|
36
36
|
subscription_options = {}
|
37
|
-
|
38
|
-
queue_options[:auto_delete] = false
|
39
|
-
else
|
40
|
-
subscription_options[:ack] = true
|
41
|
-
end
|
37
|
+
subscription_options[:ack] = true
|
42
38
|
queue_service.ready do
|
43
39
|
queue_service.queue(service_name.to_s, queue_options) do |queue|
|
44
|
-
log "subscribing to queue #{service_name.to_s}
|
40
|
+
log "subscribing to queue #{service_name.to_s}"
|
45
41
|
queue.subscribe(subscription_options) do |delivery_info, payload|
|
46
|
-
|
47
|
-
queue_service.acknowledge delivery_info
|
42
|
+
process_queue_message service_name, payload, delivery_info
|
43
|
+
queue_service.acknowledge delivery_info
|
48
44
|
end
|
49
45
|
end
|
50
46
|
end
|
51
47
|
end
|
52
48
|
|
53
|
-
def request(name, kind, message,
|
54
|
-
log "Preparing request: #{name}.#{kind} #{message.inspect[0..500]}\t|| #{
|
55
|
-
options
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
49
|
+
def request(name, kind, message, timeout: RPC_DEFAULT_TIMEOUT, fast: false)
|
50
|
+
log "Preparing request: #{name}.#{kind} #{message.inspect[0..500]}\t|| timeout: #{timeout} fast: #{fast}"
|
51
|
+
options = {
|
52
|
+
timeout: timeout,
|
53
|
+
routing_key: name.to_s
|
54
|
+
}
|
55
|
+
if fast
|
56
|
+
waiter = nil
|
57
|
+
else
|
58
|
+
correlation_id = Combi::Correlation.generate
|
59
|
+
options[:correlation_id] = correlation_id
|
60
|
+
waiter = @response_store.wait_for correlation_id, timeout
|
61
|
+
end
|
60
62
|
queue_service.next_ready_only do
|
61
63
|
log "Making request: #{name}.#{kind} #{message.inspect[0..500]}\t|| #{options.inspect[0..500]}"
|
62
|
-
queue_service.
|
64
|
+
queue_service.publish_request(kind, message, options)
|
63
65
|
end
|
64
66
|
waiter
|
65
67
|
end
|
66
68
|
|
67
|
-
def
|
69
|
+
def process_queue_message(service_name, request, delivery_info)
|
68
70
|
message = Yajl::Parser.parse request, symbolize_keys: true
|
69
71
|
kind = message[:kind]
|
70
72
|
payload = message[:payload]
|
71
73
|
options = message[:options]
|
72
74
|
response = invoke_service(service_name, kind, payload)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
75
|
+
if delivery_info.reply_to
|
76
|
+
response.callback do |service_response|
|
77
|
+
queue_service.respond service_response, delivery_info
|
78
|
+
end
|
79
|
+
response.errback do |service_response|
|
80
|
+
failure_response = { error: service_response }
|
81
|
+
queue_service.respond failure_response, delivery_info
|
82
|
+
end
|
79
83
|
end
|
80
84
|
end
|
81
85
|
|
@@ -32,10 +32,6 @@ module Combi
|
|
32
32
|
session && session.close
|
33
33
|
end
|
34
34
|
|
35
|
-
def ws
|
36
|
-
@ws
|
37
|
-
end
|
38
|
-
|
39
35
|
end
|
40
36
|
|
41
37
|
class Client
|
@@ -52,7 +48,7 @@ module Combi
|
|
52
48
|
end
|
53
49
|
|
54
50
|
def stop!
|
55
|
-
|
51
|
+
ws && ws.close
|
56
52
|
@bus.log "stop requested"
|
57
53
|
end
|
58
54
|
|
@@ -90,7 +86,6 @@ module Combi
|
|
90
86
|
end
|
91
87
|
|
92
88
|
def ws
|
93
|
-
@bus.log "ws present: #{@ws != nil}"
|
94
89
|
@ws
|
95
90
|
end
|
96
91
|
|
@@ -175,32 +170,41 @@ module Combi
|
|
175
170
|
response = {error: {klass: e.class.name, message: e.message, backtrace: e.backtrace } }
|
176
171
|
end
|
177
172
|
|
178
|
-
|
173
|
+
if message[:correlation_id]
|
174
|
+
# The client is insterested in a response
|
175
|
+
msg = {result: 'ok', correlation_id: message[:correlation_id]}
|
179
176
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
ws.send serialized
|
177
|
+
response.callback do |service_response|
|
178
|
+
msg[:response] = service_response
|
179
|
+
send_response ws, msg
|
180
|
+
end
|
181
|
+
response.errback do |service_response|
|
182
|
+
msg[:response] = {error: service_response}
|
183
|
+
send_response ws, msg
|
184
|
+
end
|
189
185
|
end
|
190
186
|
end
|
191
187
|
|
192
|
-
def
|
193
|
-
|
194
|
-
|
188
|
+
def send_response(ws, message)
|
189
|
+
serialized = Yajl::Encoder.encode message
|
190
|
+
ws.send serialized
|
191
|
+
end
|
192
|
+
|
193
|
+
def request(name, kind, message, timeout: RPC_DEFAULT_TIMEOUT, fast: false, ws: nil)
|
195
194
|
msg = {
|
196
195
|
service: name,
|
197
196
|
kind: kind,
|
198
|
-
payload: message
|
199
|
-
correlation_id: correlation_id
|
197
|
+
payload: message
|
200
198
|
}
|
201
|
-
|
199
|
+
if fast
|
200
|
+
waiter = nil
|
201
|
+
else
|
202
|
+
correlation_id = Combi::Correlation.generate
|
203
|
+
msg[:correlation_id] = correlation_id
|
204
|
+
waiter = @response_store.wait_for(correlation_id, timeout)
|
205
|
+
end
|
202
206
|
@ready.callback do |r|
|
203
|
-
web_socket = @machine.ws
|
207
|
+
web_socket = @machine.respond_to?(:ws) ? @machine.ws : ws
|
204
208
|
unless web_socket.nil?
|
205
209
|
serialized = Yajl::Encoder.encode msg
|
206
210
|
log "sending request #{serialized}"
|
data/lib/combi/queue_service.rb
CHANGED
@@ -114,12 +114,13 @@ module Combi
|
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
117
|
-
def
|
118
|
-
|
119
|
-
|
117
|
+
def publish_request(kind, message, options = {})
|
118
|
+
if options.has_key? :correlation_id
|
119
|
+
# wants a response
|
120
|
+
options[:reply_to] = @rpc_queue.name
|
121
|
+
end
|
120
122
|
options[:expiration] = ((options[:timeout] || RPC_DEFAULT_TIMEOUT) * 1000).to_i
|
121
|
-
|
122
|
-
options[:reply_to] ||= @rpc_queue.name
|
123
|
+
log "sending request #{kind} #{message.inspect[0..500]} with options #{options.inspect}"
|
123
124
|
request = Yajl::Encoder.encode kind: kind, payload: message, options: {}
|
124
125
|
publish request, options
|
125
126
|
end
|
data/lib/combi/service.rb
CHANGED
@@ -6,6 +6,7 @@ module Combi
|
|
6
6
|
context[:service_bus] = service_bus
|
7
7
|
setup_context(context)
|
8
8
|
setup_services
|
9
|
+
self
|
9
10
|
end
|
10
11
|
|
11
12
|
def setup_context(context)
|
@@ -32,10 +33,6 @@ module Combi
|
|
32
33
|
[]
|
33
34
|
end
|
34
35
|
|
35
|
-
def fast_actions
|
36
|
-
[]
|
37
|
-
end
|
38
|
-
|
39
36
|
def remote_methods
|
40
37
|
@_REMOTE_METHODS ||= public_methods(false) - Combi::Service.public_instance_methods
|
41
38
|
end
|
data/lib/combi/version.rb
CHANGED
@@ -17,7 +17,7 @@ describe 'Combi::Bus' do
|
|
17
17
|
Given(:path) { 'class/remote' }
|
18
18
|
When { bus.add_service service_definition }
|
19
19
|
Then { bus.routes.keys.length == 1 }
|
20
|
-
And { bus.routes[path]
|
20
|
+
And { bus.routes[path] == service_definition }
|
21
21
|
end
|
22
22
|
|
23
23
|
context 'via modules' do
|
@@ -34,7 +34,7 @@ describe 'Combi::Bus' do
|
|
34
34
|
puts bus.routes.keys.inspect
|
35
35
|
}
|
36
36
|
Then { bus.routes.keys.length == 1 }
|
37
|
-
And { bus.routes[path]
|
37
|
+
And { bus.routes[path].is_a? service_definition }
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -49,6 +49,24 @@ describe 'Combi::Queue' do
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
+
context 'fire and forget' do
|
53
|
+
describe 'does not send a response' do
|
54
|
+
When(:service) { provider.add_service null_service }
|
55
|
+
Then do
|
56
|
+
em do
|
57
|
+
expect(provider.queue_service).not_to receive(:respond)
|
58
|
+
expect(service).to receive(:do_it) do
|
59
|
+
done
|
60
|
+
provider.stop!
|
61
|
+
consumer.stop!
|
62
|
+
end
|
63
|
+
prepare
|
64
|
+
consumer.request :null, :do_it, {}, fast: true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
52
70
|
context "it resist a reconnection" do
|
53
71
|
puts "VERY UNSTABLE TEST"
|
54
72
|
When(:service) { provider.add_service null_service }
|
@@ -46,6 +46,23 @@ describe 'Combi::WebSocket' do
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
context 'fire and forget' do
|
50
|
+
describe 'does not send a response' do
|
51
|
+
When(:service) { provider.add_service null_service }
|
52
|
+
Then do
|
53
|
+
em do
|
54
|
+
expect(provider).not_to receive(:send_response)
|
55
|
+
expect(service).to receive(:do_it) do
|
56
|
+
done
|
57
|
+
provider.stop!
|
58
|
+
consumer.stop!
|
59
|
+
end
|
60
|
+
prepare
|
61
|
+
consumer.request :null, :do_it, {}, fast: true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
49
66
|
|
50
67
|
context 'it notify when the connection is opened' do
|
51
68
|
Then do
|
@@ -38,165 +38,254 @@ shared_examples_for "standard_bus" do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
Given(:calculator_service) do
|
42
|
+
Module.new do
|
43
|
+
def actions; [:calculator]; end
|
44
|
+
def incr(params)
|
45
|
+
@counter += 1
|
46
|
+
end
|
47
|
+
def initialize
|
48
|
+
@counter = 0
|
49
|
+
end
|
50
|
+
def counter
|
51
|
+
@counter
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
41
56
|
Given(:finalize) do
|
42
57
|
provider.stop!
|
43
58
|
consumer.stop!
|
44
59
|
end
|
45
60
|
|
46
|
-
context '
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
61
|
+
context 'fire and forget' do
|
62
|
+
context 'can invoke services' do
|
63
|
+
When(:service) { provider.add_service calculator_service }
|
64
|
+
When(:params) { { who: 'world' } }
|
65
|
+
When(:service_response) do
|
66
|
+
srv_resp = "UNSET"
|
67
|
+
em do
|
68
|
+
prepare
|
69
|
+
EM.synchrony do
|
70
|
+
srv_resp = consumer.request(:calculator, :incr, {}, {fast: true})
|
71
|
+
spec_waiter = EM::DefaultDeferrable.new
|
72
|
+
EM.add_periodic_timer 0.1 do
|
73
|
+
spec_waiter.succeed service.counter if service.counter == 1
|
74
|
+
end
|
75
|
+
EM::Synchrony.sync spec_waiter
|
76
|
+
done
|
77
|
+
finalize
|
78
|
+
end
|
57
79
|
end
|
80
|
+
srv_resp
|
58
81
|
end
|
82
|
+
Then { service_response.should_not be_a EM::Deferrable }
|
83
|
+
And { service_response.should be_nil }
|
84
|
+
And { service.counter.should eq 1 }
|
59
85
|
end
|
60
|
-
end
|
61
86
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
done(time_base) #timeout response must came before this timeout
|
87
|
+
context 'ignores service errors' do
|
88
|
+
Given(:error_message) { 'service is broken' }
|
89
|
+
When(:service) { provider.add_service broken_service }
|
90
|
+
Then do
|
91
|
+
em do
|
92
|
+
prepare
|
93
|
+
EM.synchrony do
|
94
|
+
service_result = consumer.request(:shout_error, :do_it, {message: error_message}, { fast: true })
|
95
|
+
service_result.should be_nil
|
96
|
+
done
|
97
|
+
finalize
|
98
|
+
end
|
75
99
|
end
|
76
|
-
finalize
|
77
100
|
end
|
78
101
|
end
|
79
|
-
end
|
80
102
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
finalize
|
103
|
+
context 'ignores unknown services' do
|
104
|
+
Then do
|
105
|
+
em do
|
106
|
+
prepare
|
107
|
+
EM.synchrony do
|
108
|
+
service_result = consumer.request(:mssing_service, :do_it, {}, { fast: true })
|
109
|
+
service_result.should be_nil
|
110
|
+
done
|
111
|
+
finalize
|
112
|
+
end
|
92
113
|
end
|
93
114
|
end
|
94
115
|
end
|
116
|
+
end
|
95
117
|
|
96
|
-
|
97
|
-
|
98
|
-
Then
|
118
|
+
context 'ignores service errors' do
|
119
|
+
When(:service) { provider.add_service boring_salutation_service }
|
120
|
+
Then do
|
121
|
+
em do
|
122
|
+
prepare
|
123
|
+
EM.synchrony do
|
124
|
+
service_result = consumer.request(:say_hello, :to_no_one, {}, { fast: true })
|
125
|
+
service_result.should be_nil
|
126
|
+
done
|
127
|
+
finalize
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
99
131
|
end
|
100
132
|
|
101
|
-
|
102
|
-
|
103
|
-
|
133
|
+
context 'expecting response' do
|
134
|
+
context 'can invoke services' do
|
135
|
+
When(:service) { provider.add_service boring_salutation_service }
|
136
|
+
When(:params) { { who: 'world' } }
|
137
|
+
Then do
|
138
|
+
em do
|
139
|
+
prepare
|
140
|
+
EM.synchrony do
|
141
|
+
service_result = EM::Synchrony.sync consumer.request(:say_hello, :do_it, params, { timeout: 2 })
|
142
|
+
service_result.should eq "Hello world"
|
143
|
+
done
|
144
|
+
finalize
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
104
148
|
end
|
105
149
|
|
106
|
-
context '
|
107
|
-
Given(:
|
108
|
-
|
150
|
+
context 'fails with error => Timeout::Error when the response is slow' do
|
151
|
+
Given(:time_base) { 0.01 }
|
152
|
+
When(:params) { { time: time_base*4 } }
|
153
|
+
When(:service) { provider.add_service slow_service }
|
154
|
+
Then do
|
155
|
+
em do
|
156
|
+
prepare
|
157
|
+
EM.synchrony do
|
158
|
+
service_result = EM::Synchrony.sync consumer.request(:sleep, :do_it, params, { timeout: time_base/2.0 })
|
159
|
+
service_result.should be_a Hash
|
160
|
+
service_result.should have_key :error
|
161
|
+
service_result[:error].should eq 'Timeout::Error'
|
162
|
+
done(time_base) #timeout response must came before this timeout
|
163
|
+
end
|
164
|
+
finalize
|
165
|
+
end
|
166
|
+
end
|
109
167
|
end
|
110
168
|
|
111
|
-
context '
|
112
|
-
Given(:
|
113
|
-
|
114
|
-
|
169
|
+
context 'return the same data type returned by service' do
|
170
|
+
Given(:result_container) { {} }
|
171
|
+
Given(:params) { { data: data } }
|
172
|
+
When(:service) { provider.add_service echo_service }
|
173
|
+
When('service is called') do
|
174
|
+
em do
|
175
|
+
prepare
|
176
|
+
EM.synchrony do
|
177
|
+
result_container[:result] = EM::Synchrony.sync consumer.request(:echo_this, :do_it, params)
|
178
|
+
done
|
179
|
+
finalize
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
115
183
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
Then { result_container[:result].keys.should eq data.keys.map(&:to_sym)}
|
120
|
-
And { result_container[:result].values.should eq data.values }
|
184
|
+
context 'for string' do
|
185
|
+
Given(:data) { "a simple string" }
|
186
|
+
Then { result_container[:result].should eq data}
|
121
187
|
end
|
122
|
-
|
123
|
-
|
188
|
+
|
189
|
+
context 'for numbers' do
|
190
|
+
Given(:data) { 237.324 }
|
124
191
|
Then { result_container[:result].should eq data}
|
125
192
|
end
|
126
|
-
end
|
127
193
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
194
|
+
context 'for arrays' do
|
195
|
+
Given(:data) { [1, 2, 3.0, "4", "cinco"]}
|
196
|
+
Then { result_container[:result].should eq data}
|
197
|
+
end
|
198
|
+
|
199
|
+
context 'for symbols always return a string' do
|
200
|
+
Given(:data) { :some_symbol }
|
201
|
+
Then { result_container[:result].should eq data.to_s}
|
202
|
+
end
|
203
|
+
|
204
|
+
context 'for maps' do
|
205
|
+
context 'with string keys' do
|
206
|
+
Given(:data) { {'a' => 1, 'b' => 'dos'} }
|
207
|
+
Then { result_container[:result].keys.should eq data.keys.map(&:to_sym)}
|
208
|
+
And { result_container[:result].values.should eq data.values }
|
209
|
+
end
|
210
|
+
context 'with symbol keys' do
|
211
|
+
Given(:data) { {a: 1, b: 'dos'} }
|
212
|
+
Then { result_container[:result].should eq data}
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context 'for objects returns their json version' do
|
217
|
+
Given(:custom_json) { {val: 'value'} }
|
218
|
+
Given(:custom_class) do
|
219
|
+
Class.new do
|
220
|
+
def initialize(custom_json)
|
221
|
+
@custom_json = custom_json
|
222
|
+
end
|
223
|
+
def to_json
|
224
|
+
@custom_json
|
225
|
+
end
|
137
226
|
end
|
138
227
|
end
|
228
|
+
Given(:data) { custom_class.new(custom_json).to_json}
|
229
|
+
Then { result_container[:result].should eq custom_json}
|
139
230
|
end
|
140
|
-
Given(:data) { custom_class.new(custom_json).to_json}
|
141
|
-
Then { result_container[:result].should eq custom_json}
|
142
231
|
end
|
143
|
-
end
|
144
232
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
233
|
+
context 'return something when service raise an error' do
|
234
|
+
Given(:error_message) { 'service is broken' }
|
235
|
+
When(:service) { provider.add_service broken_service }
|
236
|
+
Then do
|
237
|
+
em do
|
238
|
+
prepare
|
239
|
+
EM.synchrony do
|
240
|
+
service_result = EM::Synchrony.sync consumer.request(:shout_error, :do_it, {message: error_message}, { timeout: 0.1 })
|
241
|
+
service_result[:error].should be_a Hash
|
242
|
+
service_result[:error][:message].should eq error_message
|
243
|
+
service_result[:error][:backtrace].should_not be_nil
|
244
|
+
service_result[:error][:backtrace].should be_an Array
|
245
|
+
done
|
246
|
+
finalize
|
247
|
+
end
|
159
248
|
end
|
160
249
|
end
|
161
250
|
end
|
162
|
-
end
|
163
251
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
252
|
+
context 'return an error when requesting an unknown service' do
|
253
|
+
Given(:error_message) { Combi::Bus::UnknownStop.name }
|
254
|
+
When(:service) { provider.add_service broken_service }
|
255
|
+
Then do
|
256
|
+
em do
|
257
|
+
prepare
|
258
|
+
EM.synchrony do
|
259
|
+
begin
|
260
|
+
service_result = EM::Synchrony.sync consumer.request(:some_not_service, :do_it, {}, { timeout: 0.1 })
|
261
|
+
if defined?(Combi::Queue) and consumer.class == Combi::Queue
|
262
|
+
service_result[:error].should eq "Timeout::Error"
|
263
|
+
else
|
264
|
+
service_result[:error][:klass].should eq error_message
|
265
|
+
service_result[:error][:message].should eq 'some_not_service/do_it'
|
266
|
+
end
|
267
|
+
done
|
268
|
+
finalize
|
178
269
|
end
|
179
|
-
done
|
180
|
-
finalize
|
181
270
|
end
|
182
271
|
end
|
183
272
|
end
|
184
273
|
end
|
185
|
-
end
|
186
274
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
275
|
+
context 'return an error when requesting an unknown action for the service' do
|
276
|
+
Given(:error_message) { Combi::Bus::UnknownStop.name }
|
277
|
+
When(:service) { provider.add_service echo_service }
|
278
|
+
Then do
|
279
|
+
em do
|
280
|
+
prepare
|
281
|
+
EM.synchrony do
|
282
|
+
begin
|
283
|
+
service_result = EM::Synchrony.sync consumer.request(:echo_this, :do_other, {}, { timeout: 0.1 })
|
284
|
+
service_result[:error][:klass].should eq error_message
|
285
|
+
service_result[:error][:message].should eq 'echo_this/do_other'
|
286
|
+
done
|
287
|
+
finalize
|
288
|
+
end
|
200
289
|
end
|
201
290
|
end
|
202
291
|
end
|