mcollective-client 2.9.1 → 2.10.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 +15 -0
- data/lib/mcollective.rb +1 -1
- data/lib/mcollective/application/find.rb +2 -0
- data/lib/mcollective/application/rpc.rb +2 -12
- data/lib/mcollective/client.rb +31 -7
- data/lib/mcollective/connector/activemq.rb +11 -2
- data/lib/mcollective/connector/rabbitmq.rb +8 -2
- data/lib/mcollective/discovery/stdin.rb +4 -2
- data/lib/mcollective/rpc/client.rb +25 -0
- data/lib/mcollective/rpc/helpers.rb +15 -5
- data/lib/mcollective/rpc/stats.rb +47 -8
- data/spec/unit/mcollective/client_spec.rb +131 -38
- data/spec/unit/mcollective/connector/activemq_spec.rb +47 -1
- data/spec/unit/mcollective/connector/rabbitmq_spec.rb +89 -2
- data/spec/unit/mcollective/rpc/client_spec.rb +39 -2
- data/spec/unit/mcollective/rpc/helpers_spec.rb +6 -0
- data/spec/unit/mcollective/rpc/stats_spec.rb +46 -2
- metadata +205 -213
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZWEwMDY2OTlmMTkwOWM4NGRjODVmYzQzMTk1ZGJmN2M4MDA0MTdlZg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MjAyNjQ5NDQxZTE1MmM1NzEwODcwMDU1MTQzNGVlNmNhYjdkZDcyMw==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NjNjZWZiZjIzMTk5ODE1ZTNkZDVmYThhMGNmNzFhNzY4ZGViMGJiNWU0OGU3
|
10
|
+
MDcyMTlhNjEyZDI3ZGZiMjE4YzVjNzk2OTVkOGY2ZDdlZjg5MTFjNTcwOWUx
|
11
|
+
N2YzZDU4YTg1MThhZWEwZTVhYjQ4NTk1ZDNlZWU2ZTc0ODRhOWQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
Mjc1NjBiNjJjNWMyYjljNDE0OWFiZmE3OWYwOGNmODEzZmE2ZmIxNWJhNDdk
|
14
|
+
NzA0MmQ5ZmI3Y2JjYmI5ODIwMGE4NzcwMjNmZTdkOWJhYmRkOGJjZWVjN2Vk
|
15
|
+
Njg2YzZiNGI2NThjYWQ2MjA4ZTA3NDUyNDA0M2FhOTgxYmI3MGE=
|
data/lib/mcollective.rb
CHANGED
@@ -96,18 +96,8 @@ class MCollective::Application::Rpc<MCollective::Application
|
|
96
96
|
puts "Request sent with id: " + mc.send(configuration[:action], configuration[:arguments])
|
97
97
|
else
|
98
98
|
discover_args = {:verbose => true}
|
99
|
-
|
100
|
-
|
101
|
-
# and someone has piped us some data
|
102
|
-
# Then we assume it's a discovery list - this can be either:
|
103
|
-
# - list of hosts in plaintext
|
104
|
-
# - JSON that came from another rpc or printrpc
|
105
|
-
if mc.default_discovery_method && !STDIN.tty? && !STDIN.eof?
|
106
|
-
# Then we override discovery to try to grok the data on STDIN
|
107
|
-
mc.discovery_method = 'stdin'
|
108
|
-
mc.discovery_options = 'auto'
|
109
|
-
discover_args = {:verbose => false}
|
110
|
-
end
|
99
|
+
|
100
|
+
mc.detect_and_set_stdin_discovery
|
111
101
|
|
112
102
|
mc.discover discover_args
|
113
103
|
|
data/lib/mcollective/client.rb
CHANGED
@@ -159,10 +159,10 @@ module MCollective
|
|
159
159
|
#
|
160
160
|
# It returns a hash of times and timeouts for discovery and total run is taken from the options
|
161
161
|
# hash which in turn is generally built using MCollective::Optionparser
|
162
|
-
def req(body, agent=nil, options=false, waitfor=
|
162
|
+
def req(body, agent=nil, options=false, waitfor=[], &block)
|
163
163
|
if body.is_a?(Message)
|
164
164
|
agent = body.agent
|
165
|
-
waitfor = body.discovered_hosts
|
165
|
+
waitfor = body.discovered_hosts || []
|
166
166
|
@options = body.options
|
167
167
|
end
|
168
168
|
|
@@ -170,12 +170,11 @@ module MCollective
|
|
170
170
|
threaded = @options[:threaded]
|
171
171
|
timeout = @discoverer.discovery_timeout(@options[:timeout], @options[:filter])
|
172
172
|
request = createreq(body, agent, @options[:filter])
|
173
|
-
publish_timeout = @options[:publish_timeout]
|
173
|
+
publish_timeout = @options[:publish_timeout] || @config.publish_timeout
|
174
174
|
stat = {:starttime => Time.now.to_f, :discoverytime => 0, :blocktime => 0, :totaltime => 0}
|
175
175
|
STDOUT.sync = true
|
176
176
|
hosts_responded = 0
|
177
177
|
|
178
|
-
|
179
178
|
begin
|
180
179
|
if threaded
|
181
180
|
hosts_responded = threaded_req(request, publish_timeout, timeout, waitfor, &block)
|
@@ -238,16 +237,41 @@ module MCollective
|
|
238
237
|
def start_receiver(requestid, waitfor, timeout, &block)
|
239
238
|
Log.debug("Starting response receiver with timeout of #{timeout}")
|
240
239
|
hosts_responded = 0
|
240
|
+
|
241
|
+
if (waitfor.is_a?(Array))
|
242
|
+
unfinished = Hash.new(0)
|
243
|
+
waitfor.each {|w| unfinished[w] += 1}
|
244
|
+
else
|
245
|
+
unfinished = []
|
246
|
+
end
|
247
|
+
|
241
248
|
begin
|
242
249
|
Timeout.timeout(timeout) do
|
243
|
-
|
250
|
+
loop do
|
244
251
|
resp = receive(requestid)
|
245
252
|
yield resp.payload
|
246
253
|
hosts_responded += 1
|
247
|
-
|
254
|
+
|
255
|
+
if (waitfor.is_a?(Array))
|
256
|
+
sender = resp.payload[:senderid]
|
257
|
+
if unfinished[sender] <= 1
|
258
|
+
unfinished.delete(sender)
|
259
|
+
else
|
260
|
+
unfinished[sender] -= 1
|
261
|
+
end
|
262
|
+
|
263
|
+
break if !waitfor.empty? && unfinished.empty?
|
264
|
+
else
|
265
|
+
break unless waitfor == 0 || hosts_responded < waitfor
|
266
|
+
end
|
267
|
+
end
|
248
268
|
end
|
249
269
|
rescue Timeout::Error => e
|
250
|
-
if (
|
270
|
+
if waitfor.is_a?(Array)
|
271
|
+
if !unfinished.empty?
|
272
|
+
Log.warn("Could not receive all responses. Did not receive responses from #{unfinished.keys.join(', ')}")
|
273
|
+
end
|
274
|
+
elsif (waitfor > hosts_responded)
|
251
275
|
Log.warn("Could not receive all responses. Expected : #{waitfor}. Received : #{hosts_responded}")
|
252
276
|
end
|
253
277
|
end
|
@@ -541,6 +541,7 @@ module MCollective
|
|
541
541
|
raise("Unknown target type #{type}") unless [:directed, :broadcast, :reply, :request, :direct_request].include?(type)
|
542
542
|
raise("Unknown collective '#{collective}' known collectives are '#{@config.collectives.join ', '}'") unless @config.collectives.include?(collective)
|
543
543
|
|
544
|
+
agents_multiplex = get_bool_option("activemq.agents_multiplex", "false")
|
544
545
|
target = {:name => nil, :headers => {}}
|
545
546
|
|
546
547
|
case type
|
@@ -548,10 +549,18 @@ module MCollective
|
|
548
549
|
target[:name] = ["/queue/" + collective, :reply, "#{Config.instance.identity}_#{$$}", Client.request_sequence].join(".")
|
549
550
|
|
550
551
|
when :broadcast
|
551
|
-
|
552
|
+
if agents_multiplex
|
553
|
+
target[:name] = ["/topic/" + collective, :agents].join(".")
|
554
|
+
else
|
555
|
+
target[:name] = ["/topic/" + collective, agent, :agent].join(".")
|
556
|
+
end
|
552
557
|
|
553
558
|
when :request
|
554
|
-
|
559
|
+
if agents_multiplex
|
560
|
+
target[:name] = ["/topic/" + collective, :agents].join(".")
|
561
|
+
else
|
562
|
+
target[:name] = ["/topic/" + collective, agent, :agent].join(".")
|
563
|
+
end
|
555
564
|
|
556
565
|
when :direct_request
|
557
566
|
target[:name] = ["/queue/" + collective, :nodes].join(".")
|
@@ -387,6 +387,7 @@ module MCollective
|
|
387
387
|
raise("Unknown target type #{type}") unless [:directed, :broadcast, :reply, :request, :direct_request].include?(type)
|
388
388
|
raise("Unknown collective '#{collective}' known collectives are '#{@config.collectives.join ', '}'") unless @config.collectives.include?(collective)
|
389
389
|
|
390
|
+
agents_multiplex = get_bool_option("rabbitmq.agents_multiplex", "false")
|
390
391
|
target = {:name => "", :headers => {}, :id => nil}
|
391
392
|
|
392
393
|
if reply_to
|
@@ -402,13 +403,18 @@ module MCollective
|
|
402
403
|
target[:id] = "mcollective_%s_replies" % agent
|
403
404
|
|
404
405
|
when :broadcast, :request # publishing a request to all nodes with an agent
|
405
|
-
|
406
|
+
if agents_multiplex
|
407
|
+
target[:name] = "/exchange/%s_broadcast" % collective
|
408
|
+
target[:id] = "%s_broadcast" % collective
|
409
|
+
else
|
410
|
+
target[:name] = "/exchange/%s_broadcast/%s" % [collective, agent]
|
411
|
+
target[:id] = "%s_broadcast_%s" % [collective, agent]
|
412
|
+
end
|
406
413
|
if reply_to
|
407
414
|
target[:headers]["reply-to"] = reply_to
|
408
415
|
else
|
409
416
|
target[:headers]["reply-to"] = reply_path
|
410
417
|
end
|
411
|
-
target[:id] = "%s_broadcast_%s" % [collective, agent]
|
412
418
|
|
413
419
|
when :direct_request # a request to a specific node
|
414
420
|
raise "Directed requests need to have a node identity" unless node
|
@@ -18,7 +18,7 @@ module MCollective
|
|
18
18
|
file = STDIN.read
|
19
19
|
|
20
20
|
if file =~ /^\s*$/
|
21
|
-
|
21
|
+
raise("data piped on STDIN contained only whitespace - could not discover hosts from it.")
|
22
22
|
end
|
23
23
|
|
24
24
|
if type == 'auto'
|
@@ -29,8 +29,10 @@ module MCollective
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
Log.debug("Parsing STDIN input as type %s" % type)
|
33
|
+
|
32
34
|
if type == 'json'
|
33
|
-
hosts =
|
35
|
+
hosts = RPC::Helpers.extract_hosts_from_json(file)
|
34
36
|
elsif type == 'text'
|
35
37
|
hosts = file.split("\n")
|
36
38
|
else
|
@@ -119,6 +119,12 @@ module MCollective
|
|
119
119
|
@stdout = STDOUT
|
120
120
|
@stdout.sync = true
|
121
121
|
end
|
122
|
+
|
123
|
+
if initial_options[:stdin]
|
124
|
+
@stdin = initial_options[:stdin]
|
125
|
+
else
|
126
|
+
@stdin = STDIN
|
127
|
+
end
|
122
128
|
end
|
123
129
|
|
124
130
|
# Disconnects cleanly from the middleware
|
@@ -459,6 +465,24 @@ module MCollective
|
|
459
465
|
agent_filter @agent
|
460
466
|
end
|
461
467
|
|
468
|
+
# Detects data on STDIN and sets the STDIN discovery method
|
469
|
+
#
|
470
|
+
# IF the discovery method hasn't been explicitly overridden
|
471
|
+
# and we're not being run interactively,
|
472
|
+
# and someone has piped us some data
|
473
|
+
#
|
474
|
+
# Then we assume it's a discovery list - this can be either:
|
475
|
+
# - list of hosts in plaintext
|
476
|
+
# - JSON that came from another rpc or printrpc
|
477
|
+
#
|
478
|
+
# Then we override discovery to try to grok the data on STDIN
|
479
|
+
def detect_and_set_stdin_discovery
|
480
|
+
if self.default_discovery_method && !@stdin.tty? && !@stdin.eof?
|
481
|
+
self.discovery_method = 'stdin'
|
482
|
+
self.discovery_options = 'auto'
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
462
486
|
# Does discovery based on the filters set, if a discovery was
|
463
487
|
# previously done return that else do a new discovery.
|
464
488
|
#
|
@@ -845,6 +869,7 @@ module MCollective
|
|
845
869
|
end
|
846
870
|
|
847
871
|
@stats.noresponsefrom.concat @client.stats[:noresponsefrom]
|
872
|
+
@stats.unexpectedresponsefrom.concat @client.stats[:unexpectedresponsefrom]
|
848
873
|
@stats.responses += @client.stats[:responses]
|
849
874
|
@stats.blocktime += @client.stats[:blocktime] + sleep_time
|
850
875
|
@stats.totaltime += @client.stats[:totaltime]
|
@@ -2,8 +2,8 @@ module MCollective
|
|
2
2
|
module RPC
|
3
3
|
# Various utilities for the RPC system
|
4
4
|
class Helpers
|
5
|
-
# Parse JSON output as produced by printrpc
|
6
|
-
# the "sender" of each
|
5
|
+
# Parse JSON output as produced by printrpc or puppet query
|
6
|
+
# and extract the "sender" / "certname" of each entry
|
7
7
|
#
|
8
8
|
# The simplist valid JSON based data would be:
|
9
9
|
#
|
@@ -11,6 +11,13 @@ module MCollective
|
|
11
11
|
# {"sender" => "example.com"},
|
12
12
|
# {"sender" => "another.com"}
|
13
13
|
# ]
|
14
|
+
#
|
15
|
+
# or
|
16
|
+
#
|
17
|
+
# [
|
18
|
+
# {"certname" => "example.com"},
|
19
|
+
# {"certname" => "another.com"}
|
20
|
+
# ]
|
14
21
|
def self.extract_hosts_from_json(json)
|
15
22
|
hosts = JSON.parse(json)
|
16
23
|
|
@@ -18,9 +25,12 @@ module MCollective
|
|
18
25
|
|
19
26
|
hosts.map do |host|
|
20
27
|
raise "JSON host list is not an array of Hashes" unless host.is_a?(Hash)
|
21
|
-
raise "JSON host list does not have senders in it" unless host.include?("sender")
|
22
28
|
|
23
|
-
host
|
29
|
+
unless host.include?("sender") || host.include?("certname")
|
30
|
+
raise "JSON host list does not have senders in it"
|
31
|
+
end
|
32
|
+
|
33
|
+
host["sender"] || host["certname"]
|
24
34
|
end.uniq
|
25
35
|
end
|
26
36
|
|
@@ -264,7 +274,7 @@ module MCollective
|
|
264
274
|
parser.on('--one', '-1', 'Send request to only one discovered nodes') do |v|
|
265
275
|
options[:mcollective_limit_targets] = 1
|
266
276
|
end
|
267
|
-
|
277
|
+
|
268
278
|
parser.on('--batch SIZE', 'Do requests in batches') do |v|
|
269
279
|
# validate batch string. Is it x% where x > 0 or is it an integer
|
270
280
|
if ((v =~ /^(\d+)%$/ && Integer($1) != 0) || v =~ /^(\d+)$/)
|
@@ -2,9 +2,9 @@ module MCollective
|
|
2
2
|
module RPC
|
3
3
|
# Class to wrap all the stats and to keep track of some timings
|
4
4
|
class Stats
|
5
|
-
attr_accessor :noresponsefrom, :starttime, :discoverytime, :blocktime, :responses
|
6
|
-
attr_accessor :discovered, :discovered_nodes, :okcount, :failcount, :noresponsefrom
|
7
|
-
attr_accessor :requestid, :aggregate_summary, :ddl, :aggregate_failures
|
5
|
+
attr_accessor :noresponsefrom, :unexpectedresponsefrom, :starttime, :discoverytime, :blocktime, :responses
|
6
|
+
attr_accessor :totaltime, :discovered, :discovered_nodes, :okcount, :failcount, :noresponsefrom
|
7
|
+
attr_accessor :responsesfrom, :requestid, :aggregate_summary, :ddl, :aggregate_failures
|
8
8
|
|
9
9
|
def initialize
|
10
10
|
reset
|
@@ -13,6 +13,7 @@ module MCollective
|
|
13
13
|
# Resets stats, if discovery time is set we keep it as it was
|
14
14
|
def reset
|
15
15
|
@noresponsefrom = []
|
16
|
+
@unexpectedresponsefrom = []
|
16
17
|
@responsesfrom = []
|
17
18
|
@responses = 0
|
18
19
|
@starttime = Time.now.to_f
|
@@ -23,7 +24,6 @@ module MCollective
|
|
23
24
|
@discovered_nodes = []
|
24
25
|
@okcount = 0
|
25
26
|
@failcount = 0
|
26
|
-
@noresponsefrom = []
|
27
27
|
@requestid = nil
|
28
28
|
@aggregate_summary = []
|
29
29
|
@aggregate_failures = []
|
@@ -32,6 +32,7 @@ module MCollective
|
|
32
32
|
# returns a hash of our stats
|
33
33
|
def to_hash
|
34
34
|
{:noresponsefrom => @noresponsefrom,
|
35
|
+
:unexpectedresponsefrom => @unexpectedresponsefrom,
|
35
36
|
:starttime => @starttime,
|
36
37
|
:discoverytime => @discoverytime,
|
37
38
|
:blocktime => @blocktime,
|
@@ -70,6 +71,7 @@ module MCollective
|
|
70
71
|
# Re-initializes the object with stats from the basic client
|
71
72
|
def client_stats=(stats)
|
72
73
|
@noresponsefrom = stats[:noresponsefrom]
|
74
|
+
@unexpectedresponsefrom = stats[:unexpectedresponsefrom]
|
73
75
|
@responses = stats[:responses]
|
74
76
|
@starttime = stats[:starttime]
|
75
77
|
@blocktime = stats[:blocktime]
|
@@ -115,13 +117,19 @@ module MCollective
|
|
115
117
|
def finish_request
|
116
118
|
@totaltime = @blocktime + @discoverytime
|
117
119
|
|
118
|
-
#
|
120
|
+
# figure out who responded unexpectedly
|
121
|
+
rhosts = @responsesfrom.clone
|
122
|
+
@discovered_nodes.each {|d| rhosts.delete(d)}
|
123
|
+
@unexpectedresponsefrom = rhosts
|
124
|
+
|
125
|
+
# figure out who we had no responses from
|
119
126
|
dhosts = @discovered_nodes.clone
|
120
127
|
@responsesfrom.each {|r| dhosts.delete(r)}
|
121
128
|
@noresponsefrom = dhosts
|
122
129
|
rescue
|
123
130
|
@totaltime = 0
|
124
131
|
@noresponsefrom = []
|
132
|
+
@unexpectedresponsefrom = []
|
125
133
|
end
|
126
134
|
|
127
135
|
# Helper to keep track of who we received responses from
|
@@ -225,8 +233,22 @@ module MCollective
|
|
225
233
|
end
|
226
234
|
end
|
227
235
|
|
228
|
-
|
229
|
-
|
236
|
+
no_response_r = no_response_report
|
237
|
+
unexpected_response_r = unexpected_response_report
|
238
|
+
if no_response_r || unexpected_response_r
|
239
|
+
result_text << ""
|
240
|
+
end
|
241
|
+
|
242
|
+
if no_response_r != ""
|
243
|
+
result_text << "" << no_response_r
|
244
|
+
end
|
245
|
+
|
246
|
+
if unexpected_response_r != ""
|
247
|
+
result_text << "" << unexpected_response_r
|
248
|
+
end
|
249
|
+
|
250
|
+
if no_response_r || unexpected_response_r
|
251
|
+
result_text << ""
|
230
252
|
end
|
231
253
|
|
232
254
|
result_text.join("\n")
|
@@ -237,7 +259,6 @@ module MCollective
|
|
237
259
|
result_text = StringIO.new
|
238
260
|
|
239
261
|
if @noresponsefrom.size > 0
|
240
|
-
result_text.puts
|
241
262
|
result_text.puts Util.colorize(:red, "No response from:")
|
242
263
|
result_text.puts
|
243
264
|
|
@@ -248,8 +269,26 @@ module MCollective
|
|
248
269
|
@noresponsefrom.sort.in_groups_of(fields_num) do |c|
|
249
270
|
result_text.puts format % c
|
250
271
|
end
|
272
|
+
end
|
251
273
|
|
274
|
+
result_text.string
|
275
|
+
end
|
276
|
+
|
277
|
+
# Returns a blob of text indicating what nodes responded but weren't discovered
|
278
|
+
def unexpected_response_report
|
279
|
+
result_text = StringIO.new
|
280
|
+
|
281
|
+
if @unexpectedresponsefrom.size > 0
|
282
|
+
result_text.puts Util.colorize(:red, "Unexpected response from:")
|
252
283
|
result_text.puts
|
284
|
+
|
285
|
+
field_size = Util.field_size(@unexpectedresponsefrom, 30)
|
286
|
+
fields_num = Util.field_number(field_size)
|
287
|
+
format = " " + ( " %-#{field_size}s" * fields_num )
|
288
|
+
|
289
|
+
@unexpectedresponsefrom.sort.in_groups_of(fields_num) do |c|
|
290
|
+
result_text.puts format % c
|
291
|
+
end
|
253
292
|
end
|
254
293
|
|
255
294
|
result_text.string
|
@@ -205,14 +205,25 @@ module MCollective
|
|
205
205
|
|
206
206
|
it "should thread the publisher and receiver if configured" do
|
207
207
|
client.instance_variable_get(:@options)[:threaded] = true
|
208
|
-
client.expects(:threaded_req).with(request,
|
208
|
+
client.expects(:threaded_req).with(request, 2, 0, ['rspec'])
|
209
209
|
message.options[:threaded] = true
|
210
210
|
client.req(message)
|
211
211
|
end
|
212
212
|
|
213
213
|
it "should not thread the publisher and receiver if configured" do
|
214
214
|
client.instance_variable_set(:@threaded, false)
|
215
|
-
client.expects(:unthreaded_req).with(request,
|
215
|
+
client.expects(:unthreaded_req).with(request, 2, 0, ['rspec'])
|
216
|
+
client.req(message)
|
217
|
+
end
|
218
|
+
|
219
|
+
it "uses the publish_timeout from options when passed as an option" do
|
220
|
+
client.expects(:unthreaded_req).with(request, 5, 0, ['rspec'])
|
221
|
+
client.req(message, nil, message.options.merge(:publish_timeout => 5))
|
222
|
+
end
|
223
|
+
|
224
|
+
it "uses the publish_timeout from config when passed as a config value" do
|
225
|
+
client.expects(:unthreaded_req).with(request, 10, 0, ['rspec'])
|
226
|
+
client.instance_variable_get(:@config).expects(:publish_timeout).returns(10)
|
216
227
|
client.req(message)
|
217
228
|
end
|
218
229
|
end
|
@@ -267,50 +278,132 @@ module MCollective
|
|
267
278
|
end
|
268
279
|
|
269
280
|
describe "#start_receiver" do
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
281
|
+
describe "waitfor is a number" do
|
282
|
+
it "should go into a receive loop and receive until it reaches waitfor" do
|
283
|
+
results = []
|
284
|
+
Timeout.stubs(:timeout).yields
|
285
|
+
message = mock
|
286
|
+
client.stubs(:receive).with("erfs123").returns(message)
|
287
|
+
message.stubs(:payload).returns("msg1", "msg2", "msg3")
|
288
|
+
client.start_receiver("erfs123", 3, 5) do |msg|
|
289
|
+
results << msg
|
290
|
+
end
|
291
|
+
results.should == ["msg1", "msg2", "msg3"]
|
278
292
|
end
|
279
|
-
results.should == ["msg1", "msg2", "msg3"]
|
280
|
-
end
|
281
293
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
294
|
+
it "should log a warning if a timeout occurs" do
|
295
|
+
results = []
|
296
|
+
Timeout.stubs(:timeout).yields
|
297
|
+
message = mock
|
298
|
+
client.stubs(:receive).with("erfs123").returns(message)
|
299
|
+
message.stubs(:payload).returns("msg1", "msg2", "timeout")
|
300
|
+
Log.expects(:warn).with("Could not receive all responses. Expected : 3. Received : 2")
|
301
|
+
responded = client.start_receiver("erfs123", 3, 5) do |msg|
|
302
|
+
if msg == "timeout"
|
303
|
+
raise Timeout::Error
|
304
|
+
end
|
305
|
+
results << msg
|
306
|
+
end
|
307
|
+
results.should == ["msg1", "msg2"]
|
308
|
+
responded.should == 2
|
309
|
+
end
|
310
|
+
|
311
|
+
it "should not log a warning if a the response count is larger or equal to the expected number of responses" do
|
312
|
+
results = []
|
313
|
+
Timeout.stubs(:timeout).yields
|
314
|
+
message = mock
|
315
|
+
client.stubs(:receive).with("erfs123").returns(message)
|
316
|
+
message.stubs(:payload).returns("msg1", "msg2", "timeout")
|
317
|
+
Log.expects(:warn).never
|
318
|
+
responded = client.start_receiver("erfs123", 2, 5) do |msg|
|
319
|
+
if msg == "timeout"
|
320
|
+
raise Timeout::Error
|
321
|
+
end
|
322
|
+
results << msg
|
292
323
|
end
|
293
|
-
results
|
324
|
+
results.should == ["msg1", "msg2"]
|
325
|
+
responded.should == 2
|
294
326
|
end
|
295
|
-
results.should == ["msg1", "msg2"]
|
296
|
-
responded.should == 2
|
297
327
|
end
|
298
328
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
329
|
+
describe "waitfor is an array" do
|
330
|
+
it "should go into a receive loop and receive until it matches waitfor" do
|
331
|
+
senders = ["sender1", "sender2", "sender3", "sender4"]
|
332
|
+
expected = senders.map {|s| Message.new({:callerid => "caller", :senderid => s}, nil, :type => :reply)}
|
333
|
+
results = []
|
334
|
+
Timeout.stubs(:timeout).yields
|
335
|
+
client.stubs(:receive).with("erfs123").returns(*expected)
|
336
|
+
client.start_receiver("erfs123", senders[0,3], 5) do |msg|
|
337
|
+
results << msg
|
338
|
+
end
|
339
|
+
results.should == expected[0,3].map {|m| m.payload}
|
340
|
+
end
|
341
|
+
|
342
|
+
it "receive until it gets all expected responses" do
|
343
|
+
senders = ["sender1", "sender2", "sender3", "sender4"]
|
344
|
+
expected = senders.map {|s| Message.new({:callerid => "caller", :senderid => s}, nil, :type => :reply)}
|
345
|
+
results = []
|
346
|
+
Timeout.stubs(:timeout).yields
|
347
|
+
client.stubs(:receive).with("erfs123").returns(*expected)
|
348
|
+
client.start_receiver("erfs123", senders[1,3], 5) do |msg|
|
349
|
+
results << msg
|
350
|
+
end
|
351
|
+
results.should == expected.map {|m| m.payload}
|
352
|
+
end
|
353
|
+
|
354
|
+
it "should log a warning if a timeout occurs" do
|
355
|
+
senders = ["sender1", "sender2", "sender3"]
|
356
|
+
messages = ["msg1", "msg2", "timeout"]
|
357
|
+
expected = senders.zip(messages).map {|s, m| Message.new({:callerid => "caller", :senderid => s, :body => m}, nil, :type => :reply)}
|
358
|
+
results = []
|
359
|
+
Timeout.stubs(:timeout).yields
|
360
|
+
client.stubs(:receive).with("erfs123").returns(*expected)
|
361
|
+
Log.expects(:warn).with("Could not receive all responses. Did not receive responses from sender3")
|
362
|
+
responded = client.start_receiver("erfs123", senders, 5) do |msg|
|
363
|
+
if msg[:body] == "timeout"
|
364
|
+
raise Timeout::Error
|
365
|
+
end
|
366
|
+
results << msg
|
367
|
+
end
|
368
|
+
results.should == expected[0,2].map {|m| m.payload}
|
369
|
+
responded.should == 2
|
370
|
+
end
|
371
|
+
|
372
|
+
it "should not log a warning if accepting all responses" do
|
373
|
+
senders = ["sender1", "sender2", "sender3"]
|
374
|
+
messages = ["msg1", "msg2", "timeout"]
|
375
|
+
expected = senders.zip(messages).map {|s, m| Message.new({:callerid => "caller", :senderid => s, :body => m}, nil, :type => :reply)}
|
376
|
+
results = []
|
377
|
+
Timeout.stubs(:timeout).yields
|
378
|
+
client.stubs(:receive).with("erfs123").returns(*expected)
|
379
|
+
Log.expects(:warn).never
|
380
|
+
responded = client.start_receiver("erfs123", [], 1) do |msg|
|
381
|
+
if msg[:body] == "timeout"
|
382
|
+
raise Timeout::Error
|
383
|
+
end
|
384
|
+
results << msg
|
385
|
+
end
|
386
|
+
results.should == expected[0,2].map {|m| m.payload}
|
387
|
+
responded.should == 2
|
388
|
+
end
|
389
|
+
|
390
|
+
it "should not log a warning if the response count is larger or equal to the expected number of responses" do
|
391
|
+
senders = ["sender1", "sender2", "sender3"]
|
392
|
+
messages = ["msg1", "msg2", "timeout"]
|
393
|
+
expected = senders.zip(messages).map {|s, m| Message.new({:callerid => "caller", :senderid => s, :body => m}, nil, :type => :reply)}
|
394
|
+
results = []
|
395
|
+
Timeout.stubs(:timeout).yields
|
396
|
+
client.stubs(:receive).with("erfs123").returns(*expected)
|
397
|
+
Log.expects(:warn).never
|
398
|
+
responded = client.start_receiver("erfs123", senders[0,2], 5) do |msg|
|
399
|
+
if msg[:body] == "timeout"
|
400
|
+
raise Timeout::Error
|
401
|
+
end
|
402
|
+
results << msg
|
309
403
|
end
|
310
|
-
results
|
404
|
+
results.should == expected[0,2].map {|m| m.payload}
|
405
|
+
responded.should == 2
|
311
406
|
end
|
312
|
-
results.should == ["msg1", "msg2"]
|
313
|
-
responded.should == 2
|
314
407
|
end
|
315
408
|
end
|
316
409
|
|