right_agent 0.6.6 → 0.9.3

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 (46) hide show
  1. data/lib/right_agent/agent.rb +26 -25
  2. data/lib/right_agent/agent_config.rb +28 -2
  3. data/lib/right_agent/command/command_constants.rb +2 -2
  4. data/lib/right_agent/core_payload_types/executable_bundle.rb +3 -21
  5. data/lib/right_agent/core_payload_types/login_user.rb +19 -4
  6. data/lib/right_agent/core_payload_types/recipe_instantiation.rb +7 -1
  7. data/lib/right_agent/core_payload_types/right_script_instantiation.rb +7 -1
  8. data/lib/right_agent/dispatcher.rb +6 -19
  9. data/lib/right_agent/idempotent_request.rb +72 -17
  10. data/lib/right_agent/monkey_patches/ruby_patch.rb +0 -1
  11. data/lib/right_agent/monkey_patches.rb +0 -1
  12. data/lib/right_agent/operation_result.rb +27 -4
  13. data/lib/right_agent/packets.rb +47 -23
  14. data/lib/right_agent/platform/darwin.rb +33 -2
  15. data/lib/right_agent/platform/linux.rb +98 -2
  16. data/lib/right_agent/platform/windows.rb +41 -6
  17. data/lib/right_agent/platform.rb +11 -2
  18. data/lib/right_agent/scripts/agent_controller.rb +2 -1
  19. data/lib/right_agent/scripts/agent_deployer.rb +2 -2
  20. data/lib/right_agent/scripts/stats_manager.rb +7 -3
  21. data/lib/right_agent/sender.rb +45 -28
  22. data/lib/right_agent.rb +2 -5
  23. data/right_agent.gemspec +5 -3
  24. data/spec/agent_config_spec.rb +1 -1
  25. data/spec/agent_spec.rb +26 -20
  26. data/spec/core_payload_types/login_user_spec.rb +7 -3
  27. data/spec/idempotent_request_spec.rb +218 -48
  28. data/spec/operation_result_spec.rb +19 -0
  29. data/spec/packets_spec.rb +42 -1
  30. data/spec/platform/darwin.rb +11 -0
  31. data/spec/platform/linux.rb +23 -0
  32. data/spec/platform/linux_volume_manager_spec.rb +43 -43
  33. data/spec/platform/platform_spec.rb +35 -32
  34. data/spec/platform/windows.rb +11 -0
  35. data/spec/sender_spec.rb +21 -25
  36. metadata +47 -40
  37. data/lib/right_agent/broker_client.rb +0 -686
  38. data/lib/right_agent/ha_broker_client.rb +0 -1327
  39. data/lib/right_agent/monkey_patches/amqp_patch.rb +0 -274
  40. data/lib/right_agent/monkey_patches/ruby_patch/string_patch.rb +0 -107
  41. data/lib/right_agent/stats_helper.rb +0 -745
  42. data/spec/broker_client_spec.rb +0 -962
  43. data/spec/ha_broker_client_spec.rb +0 -1695
  44. data/spec/monkey_patches/amqp_patch_spec.rb +0 -100
  45. data/spec/monkey_patches/string_patch_spec.rb +0 -99
  46. data/spec/stats_helper_spec.rb +0 -686
@@ -1,1695 +0,0 @@
1
- #
2
- # Copyright (c) 2009-2011 RightScale Inc
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
-
23
- require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
24
-
25
- describe RightScale::HABrokerClient do
26
-
27
- include FlexMock::ArgumentTypes
28
-
29
- before(:each) do
30
- @log = flexmock(RightScale::Log)
31
- @log.should_receive(:error).by_default.and_return { |m| raise RightScale::Log.format(*m) }
32
- @log.should_receive(:warning).by_default.and_return { |m| raise RightScale::Log.format(*m) }
33
- @log.should_receive(:info).by_default
34
- end
35
-
36
- describe "Context" do
37
-
38
- before(:each) do
39
- @packet1 = flexmock("packet1", :class => RightScale::Request, :name => "request", :type => "type1",
40
- :from => "from1", :token => "token1", :one_way => false)
41
- @packet2 = flexmock("packet2", :class => FlexMock, :name => "flexmock")
42
- @brokers = ["broker"]
43
- @options = {:option => "option"}
44
- end
45
-
46
- it "should initialize context" do
47
- context = RightScale::HABrokerClient::Context.new(@packet1, @options, @brokers)
48
- context.name.should == "request"
49
- context.type.should == "type1"
50
- context.from.should == "from1"
51
- context.token.should == "token1"
52
- context.one_way.should be_false
53
- context.options.should == @options
54
- context.brokers.should == @brokers
55
- context.failed.should == []
56
- end
57
-
58
- it "should treat type, from, token, and one_way as optional members of packet but default one_way to true" do
59
- context = RightScale::HABrokerClient::Context.new(@packet2, @options, @brokers)
60
- context.name.should == "flexmock"
61
- context.type.should be_nil
62
- context.from.should be_nil
63
- context.token.should be_nil
64
- context.one_way.should be_true
65
- context.options.should == @options
66
- context.brokers.should == @brokers
67
- context.failed.should == []
68
- end
69
-
70
- end
71
-
72
- describe "Caching" do
73
-
74
- before(:each) do
75
- flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
76
- @published = RightScale::HABrokerClient::Published.new
77
- @message1 = MessagePack.dump(:signature => "signature1")
78
- @key1 = @message1[@message1 =~ /signature/, 1000]
79
- @message2 = JSON.dump(:signature => "signature2")
80
- @key2 = @message2[@message2 =~ /signature/, 1000]
81
- @message3 = MessagePack.dump(:data => "just data")
82
- @key3 = @message3
83
- @packet1 = flexmock("packet1", :class => RightScale::Request, :name => "request", :type => "type1",
84
- :from => "from1", :token => "token1", :one_way => false)
85
- @packet2 = flexmock("packet2", :class => RightScale::Request, :name => "request", :type => "type2",
86
- :from => "from2", :token => "token2", :one_way => false)
87
- @packet3 = flexmock("packet3", :class => RightScale::Push, :name => "push", :type => "type3",
88
- :from => "from3", :token => "token3", :one_way => true)
89
- @brokers = ["broker"]
90
- @options = {:option => "option"}
91
- @context1 = RightScale::HABrokerClient::Context.new(@packet1, @options, @brokers)
92
- @context2 = RightScale::HABrokerClient::Context.new(@packet2, @options, @brokers)
93
- @context3 = RightScale::HABrokerClient::Context.new(@packet3, @options, @brokers)
94
- end
95
-
96
- it "should use message signature as cache hash key if it has one" do
97
- @published.identify(@message1).should == @key1
98
- @published.identify(@message2).should == @key2
99
- @published.identify(@message3).should == @key3
100
- end
101
-
102
- it "should store message info" do
103
- @published.store(@message1, @context1)
104
- @published.instance_variable_get(:@cache)[@key1].should == [1000000, @context1]
105
- @published.instance_variable_get(:@lru).should == [@key1]
106
- end
107
-
108
- it "should update timestamp and lru list when store to existing entry" do
109
- @published.store(@message1, @context1)
110
- @published.instance_variable_get(:@cache)[@key1].should == [1000000, @context1]
111
- @published.instance_variable_get(:@lru).should == [@key1]
112
- @published.store(@message2, @context2)
113
- @published.instance_variable_get(:@lru).should == [@key1, @key2]
114
- flexmock(Time).should_receive(:now).and_return(Time.at(1000010))
115
- @published.store(@message1, @context1)
116
- @published.instance_variable_get(:@cache)[@key1].should == [1000010, @context1]
117
- @published.instance_variable_get(:@lru).should == [@key2, @key1]
118
- end
119
-
120
- it "should remove old cache entries when store new one" do
121
- @published.store(@message1, @context1)
122
- @published.store(@message2, @context2)
123
- @published.instance_variable_get(:@cache).keys.should == [@key1, @key2]
124
- @published.instance_variable_get(:@lru).should == [@key1, @key2]
125
- flexmock(Time).should_receive(:now).and_return(Time.at(1000031))
126
- @published.store(@message3, @context3)
127
- @published.instance_variable_get(:@cache).keys.should == [@key3]
128
- @published.instance_variable_get(:@lru).should == [@key3]
129
- end
130
-
131
- it "should fetch message info and make it the most recently used" do
132
- @published.store(@message1, @context1)
133
- @published.store(@message2, @context2)
134
- @published.instance_variable_get(:@lru).should == [@key1, @key2]
135
- @published.fetch(@message1).should == @context1
136
- @published.instance_variable_get(:@lru).should == [@key2, @key1]
137
- end
138
-
139
- it "should fetch empty hash if entry not found" do
140
- @published.fetch(@message1).should be_nil
141
- @published.store(@message1, @context1)
142
- @published.fetch(@message1).should_not be_nil
143
- @published.fetch(@message2).should be_nil
144
- end
145
-
146
- end # Published
147
-
148
- context "when initializing" do
149
-
150
- before(:each) do
151
- @serializer = flexmock("Serializer")
152
- @exceptions = RightScale::StatsHelper::ExceptionStats
153
- @identity = "rs-broker-localhost-5672"
154
- @address = {:host => "localhost", :port => 5672, :index => 0}
155
- @broker = flexmock("broker_client", :identity => @identity, :usable? => true)
156
- @broker.should_receive(:return_message).by_default
157
- @broker.should_receive(:update_status).by_default
158
- flexmock(RightScale::BrokerClient).should_receive(:new).and_return(@broker).by_default
159
- @island1 = flexmock("island1", :id => 11, :broker_hosts => "second:1,first:0", :broker_ports => "5673")
160
- @island2 = flexmock("island2", :id => 22, :broker_hosts => "third:0,fourth:1", :broker_ports => nil)
161
- @islands = {11 => @island1, 22 => @island2}
162
- end
163
-
164
- it "should create a broker client for default host and port" do
165
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity, @address, @serializer,
166
- @exceptions, Hash, nil, nil).and_return(@broker).once
167
- ha = RightScale::HABrokerClient.new(@serializer)
168
- ha.brokers.should == [@broker]
169
- end
170
-
171
- it "should create broker clients for specified hosts and ports and assign index in order of creation" do
172
- address1 = {:host => "first", :port => 5672, :index => 0}
173
- broker1 = flexmock("broker_client1", :identity => "rs-broker-first-5672", :usable? => true, :return_message => true)
174
- flexmock(RightScale::BrokerClient).should_receive(:new).with("rs-broker-first-5672", address1, @serializer,
175
- RightScale::StatsHelper::ExceptionStats, Hash, nil, nil).and_return(broker1).once
176
- address2 = {:host => "second", :port => 5672, :index => 1}
177
- broker2 = flexmock("broker_client2", :identity => "rs-broker-second-5672", :usable? => true, :return_message => true)
178
- flexmock(RightScale::BrokerClient).should_receive(:new).with("rs-broker-second-5672", address2, @serializer,
179
- RightScale::StatsHelper::ExceptionStats, Hash, nil, nil).and_return(broker2).once
180
- ha = RightScale::HABrokerClient.new(@serializer, :host => "first, second", :port => 5672)
181
- ha.brokers.should == [broker1, broker2]
182
- ha.home_island.should be_nil
183
- end
184
-
185
- it "should create broker clients for specified islands" do
186
- address1 = {:host => "first", :port => 5673, :index => 0}
187
- broker1 = flexmock("broker_client1", :identity => "rs-broker-first-5673", :usable? => true, :return_message => true)
188
- flexmock(RightScale::BrokerClient).should_receive(:new).with("rs-broker-first-5673", address1, @serializer,
189
- RightScale::StatsHelper::ExceptionStats, Hash, @island1, nil).and_return(broker1).once
190
- address2 = {:host => "second", :port => 5673, :index => 1}
191
- broker2 = flexmock("broker_client2", :identity => "rs-broker-second-5673", :usable? => true, :return_message => true)
192
- flexmock(RightScale::BrokerClient).should_receive(:new).with("rs-broker-second-5673", address2, @serializer,
193
- RightScale::StatsHelper::ExceptionStats, Hash, @island1, nil).and_return(broker2).once
194
- address3 = {:host => "third", :port => 5672, :index => 0}
195
- broker3 = flexmock("broker_client3", :identity => "rs-broker-third-5672", :usable? => true, :return_message => true)
196
- flexmock(RightScale::BrokerClient).should_receive(:new).with("rs-broker-third-5672", address3, @serializer,
197
- RightScale::StatsHelper::ExceptionStats, Hash, @island2, nil).and_return(broker3).once
198
- address4 = {:host => "fourth", :port => 5672, :index => 1}
199
- broker4 = flexmock("broker_client4", :identity => "rs-broker-fourth-5672", :usable? => true, :return_message => true)
200
- flexmock(RightScale::BrokerClient).should_receive(:new).with("rs-broker-fourth-5672", address4, @serializer,
201
- RightScale::StatsHelper::ExceptionStats, Hash, @island2, nil).and_return(broker4).once
202
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => 22)
203
- ha.brokers.should == [broker3, broker4, broker2, broker1]
204
- ha.home_island.should == 22
205
- end
206
-
207
- it "should raise an ArgumentError if it cannot find the home island" do
208
- flexmock(RightScale::BrokerClient).should_receive(:new).never
209
- lambda { RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => 33) }.
210
- should raise_error(ArgumentError, /Could not find home island 33/)
211
- end
212
-
213
- it "should setup to receive returned messages from each usable broker client" do
214
- @broker.should_receive(:return_message).twice
215
- flexmock(RightScale::BrokerClient).should_receive(:new).and_return(@broker).twice
216
- RightScale::HABrokerClient.new(@serializer, :host => "first, second", :port => 5672)
217
- end
218
-
219
- end # when initializing
220
-
221
- context "when parsing user_data" do
222
-
223
- it "should extra host list from RS_rn_url and RS_rn_host" do
224
- RightScale::HABrokerClient.parse_user_data("RS_rn_url=rs@first/right_net&RS_rn_host=:0,second:1").should ==
225
- ["first:0,second:1", nil]
226
- end
227
-
228
- it "should extra port list from RS_rn_port" do
229
- RightScale::HABrokerClient.parse_user_data("RS_rn_url=rs@host/right_net&RS_rn_host=:1,host:0&RS_rn_port=5673:1,5672:0").should ==
230
- ["host:1,host:0", "5673:1,5672:0"]
231
- end
232
-
233
- it "should raise an exception if there is no user data" do
234
- lambda { RightScale::HABrokerClient.parse_user_data(nil) }.should raise_error(RightScale::HABrokerClient::NoUserData)
235
- lambda { RightScale::HABrokerClient.parse_user_data("") }.should raise_error(RightScale::HABrokerClient::NoUserData)
236
- end
237
-
238
- it "should raise an exception if there are no broker hosts defined in the data" do
239
- lambda { RightScale::HABrokerClient.parse_user_data("blah") }.should raise_error(RightScale::HABrokerClient::NoBrokerHosts)
240
- end
241
-
242
- it "should translate old host name to standard form" do
243
- RightScale::HABrokerClient.parse_user_data("RS_rn_url=rs@broker.rightscale.com/right_net").should ==
244
- ["broker1-1.rightscale.com", nil]
245
- end
246
-
247
- end # when parsing user_data
248
-
249
- context "when addressing" do
250
-
251
- it "should form list of broker addresses from specified hosts and ports" do
252
- RightScale::HABrokerClient.addresses("first,second", "5672, 5674").should ==
253
- [{:host => "first", :port => 5672, :index => 0}, {:host => "second", :port => 5674, :index => 1}]
254
- end
255
-
256
- it "should form list of broker addresses from specified hosts and ports and use ids associated with hosts" do
257
- RightScale::HABrokerClient.addresses("first:1,second:2", "5672, 5674").should ==
258
- [{:host => "first", :port => 5672, :index => 1}, {:host => "second", :port => 5674, :index => 2}]
259
- end
260
-
261
- it "should form list of broker addresses from specified hosts and ports and use ids associated with ports" do
262
- RightScale::HABrokerClient.addresses("host", "5672:0, 5674:2").should ==
263
- [{:host => "host", :port => 5672, :index => 0}, {:host => "host", :port => 5674, :index => 2}]
264
- end
265
-
266
- it "should use default host and port for broker identity if none provided" do
267
- RightScale::HABrokerClient.addresses(nil, nil).should == [{:host => "localhost", :port => 5672, :index => 0}]
268
- end
269
-
270
- it "should use default port when ports is an empty string" do
271
- RightScale::HABrokerClient.addresses("first, second", "").should ==
272
- [{:host => "first", :port => 5672, :index => 0}, {:host => "second", :port => 5672, :index => 1}]
273
- end
274
-
275
- it "should use default host when hosts is an empty string" do
276
- RightScale::HABrokerClient.addresses("", "5672, 5673").should ==
277
- [{:host => "localhost", :port => 5672, :index => 0}, {:host => "localhost", :port => 5673, :index => 1}]
278
- end
279
-
280
- it "should reuse host if there is only one but multiple ports" do
281
- RightScale::HABrokerClient.addresses("first", "5672, 5674").should ==
282
- [{:host => "first", :port => 5672, :index => 0}, {:host => "first", :port => 5674, :index => 1}]
283
- end
284
-
285
- it "should reuse port if there is only one but multiple hosts" do
286
- RightScale::HABrokerClient.addresses("first, second", 5672).should ==
287
- [{:host => "first", :port => 5672, :index => 0}, {:host => "second", :port => 5672, :index => 1}]
288
- end
289
-
290
- it "should apply ids associated with host" do
291
- RightScale::HABrokerClient.addresses("first:0, third:2", 5672).should ==
292
- [{:host => "first", :port => 5672, :index => 0}, {:host => "third", :port => 5672, :index => 2}]
293
- end
294
-
295
- it "should not allow mismatched number of hosts and ports" do
296
- runner = lambda { RightScale::HABrokerClient.addresses("first, second", "5672, 5673, 5674") }
297
- runner.should raise_exception(ArgumentError)
298
- end
299
-
300
- end # when addressing
301
-
302
- context "when identifying" do
303
-
304
- before(:each) do
305
- @serializer = flexmock("Serializer")
306
- @exceptions = RightScale::StatsHelper::ExceptionStats
307
-
308
- @address1 = {:host => "first", :port => 5672, :index => 0}
309
- @identity1 = "rs-broker-first-5672"
310
- @broker1 = flexmock("broker_client1", :identity => @identity1, :usable? => true, :return_message => true,
311
- :alias => "b0", :host => "first", :port => 5672, :index => 0)
312
- @broker1.should_receive(:island_id).and_return(nil).by_default
313
- @broker1.should_receive(:in_home_island).and_return(true).by_default
314
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity1, @address1, @serializer,
315
- @exceptions, Hash, nil, nil).and_return(@broker1).by_default
316
-
317
- @address2 = {:host => "second", :port => 5672, :index => 1}
318
- @identity2 = "rs-broker-second-5672"
319
- @broker2 = flexmock("broker_client2", :identity => @identity2, :usable? => true, :return_message => true,
320
- :alias => "b1", :host => "second", :port => 5672, :index => 1)
321
- @broker2.should_receive(:island_id).and_return(nil).by_default
322
- @broker2.should_receive(:in_home_island).and_return(true).by_default
323
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity2, @address2, @serializer,
324
- @exceptions, Hash, nil, nil).and_return(@broker2).by_default
325
-
326
- @address3 = {:host => "third", :port => 5672, :index => 2}
327
- @identity3 = "rs-broker-third-5672"
328
- @broker3 = flexmock("broker_client3", :identity => @identity3, :usable? => true, :return_message => true,
329
- :alias => "b2", :host => "third", :port => 5672, :index => 2)
330
- @broker3.should_receive(:island_id).and_return(nil).by_default
331
- @broker3.should_receive(:in_home_island).and_return(true).by_default
332
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity3, @address3, @serializer,
333
- @exceptions, Hash, nil, nil).and_return(@broker3).by_default
334
- end
335
-
336
- it "should use host and port to uniquely identity broker in AgentIdentity format" do
337
- RightScale::HABrokerClient.identity("localhost", 5672).should == "rs-broker-localhost-5672"
338
- RightScale::HABrokerClient.identity("10.21.102.23", 1234).should == "rs-broker-10.21.102.23-1234"
339
- end
340
-
341
- it "should replace '-' with '~' in host names when forming broker identity" do
342
- RightScale::HABrokerClient.identity("9-1-1", 5672).should == "rs-broker-9~1~1-5672"
343
- end
344
-
345
- it "should use default port when forming broker identity" do
346
- RightScale::HABrokerClient.identity("10.21.102.23").should == "rs-broker-10.21.102.23-5672"
347
- end
348
-
349
- it "should list broker identities" do
350
- RightScale::HABrokerClient.identities("first,second", "5672, 5674").should ==
351
- ["rs-broker-first-5672", "rs-broker-second-5674"]
352
- end
353
-
354
- it "should convert identities into aliases" do
355
- ha = RightScale::HABrokerClient.new(@serializer, :host => "first:0, third:2", :port => 5672)
356
- ha.aliases([@identity3]).should == ["b2"]
357
- ha.aliases([@identity3, @identity1]).should == ["b2", "b0"]
358
- end
359
-
360
- it "should convert identities into nil alias when unknown" do
361
- ha = RightScale::HABrokerClient.new(@serializer, :host => "first:0, third:2", :port => 5672)
362
- ha.aliases(["rs-broker-second-5672", nil]).should == [nil, nil]
363
- end
364
-
365
- it "should convert identity into alias" do
366
- ha = RightScale::HABrokerClient.new(@serializer, :host => "first:0, third:2", :port => 5672)
367
- ha.alias_(@identity3).should == "b2"
368
- end
369
-
370
- it "should convert identity into nil alias when unknown" do
371
- ha = RightScale::HABrokerClient.new(@serializer, :host => "first:0, third:2", :port => 5672)
372
- ha.alias_("rs-broker-second-5672").should == nil
373
- end
374
-
375
- it "should convert identity into parts" do
376
- ha = RightScale::HABrokerClient.new(@serializer, :host => "first:0, third:2", :port => 5672)
377
- ha.identity_parts(@identity3).should == ["third", 5672, 2, 1, nil]
378
- end
379
-
380
- it "should convert an alias into parts" do
381
- ha = RightScale::HABrokerClient.new(@serializer, :host => "first:0, third:2", :port => 5672)
382
- ha.identity_parts("b2").should == ["third", 5672, 2, 1, nil]
383
- end
384
-
385
- it "should convert unknown identity into nil parts" do
386
- ha = RightScale::HABrokerClient.new(@serializer, :host => "first:0, third:2", :port => 5672)
387
- ha.identity_parts("rs-broker-second-5672").should == [nil, nil, nil, nil, nil]
388
- end
389
-
390
- it "should get identity from identity" do
391
- ha = RightScale::HABrokerClient.new(@serializer, :host => "first:0, third:2", :port => 5672)
392
- ha.get(@identity1).should == @identity1
393
- ha.get("rs-broker-second-5672").should be_nil
394
- ha.get(@identity3).should == @identity3
395
- end
396
-
397
- it "should get identity from an alias" do
398
- ha = RightScale::HABrokerClient.new(@serializer, :host => "first:0, third:2", :port => 5672)
399
- ha.get("b0").should == @identity1
400
- ha.get("b1").should be_nil
401
- ha.get("b2").should == @identity3
402
- end
403
-
404
- it "should generate host:index list" do
405
- ha = RightScale::HABrokerClient.new(@serializer, :host => "second:1, first:0, third:2", :port => 5672)
406
- ha.hosts.should == "second:1,first:0,third:2"
407
- end
408
-
409
- it "should generate port:index list" do
410
- ha = RightScale::HABrokerClient.new(@serializer, :host => "second:1, third:2, first:0", :port => 5672)
411
- ha.ports.should == "5672:1,5672:2,5672:0"
412
- end
413
-
414
- context "when using islands" do
415
-
416
- before(:each) do
417
- @island1 = flexmock("island1", :id => 11, :broker_hosts => "second:1,first:0", :broker_ports => "5672")
418
- @island2 = flexmock("island2", :id => 22, :broker_hosts => "third:0,fourth:1", :broker_ports => nil)
419
- @islands = {11 => @island1, 22 => @island2}
420
-
421
- @broker1.should_receive(:island_id).and_return(11)
422
- @broker1.should_receive(:in_home_island).and_return(false)
423
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity1, @address1, @serializer,
424
- @exceptions, Hash, @island1, nil).and_return(@broker1)
425
-
426
- @broker2.should_receive(:island_id).and_return(11)
427
- @broker2.should_receive(:in_home_island).and_return(false)
428
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity2, @address2, @serializer,
429
- @exceptions, Hash, @island1, nil).and_return(@broker2)
430
-
431
- @address3 = {:host => "third", :port => 5672, :index => 0}
432
- @identity3 = "rs-broker-third-5672"
433
- @broker3 = flexmock("broker_client3", :identity => @identity3, :usable? => true, :return_message => true,
434
- :alias => "b0", :host => "third", :port => 5672, :index => 0)
435
- @broker3.should_receive(:island_id).and_return(22).by_default
436
- @broker3.should_receive(:in_home_island).and_return(true)
437
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity3, @address3, @serializer,
438
- @exceptions, Hash, @island2, nil).and_return(@broker3)
439
-
440
- @address4 = {:host => "fourth", :port => 5672, :index => 1}
441
- @identity4 = "rs-broker-fourth-5672"
442
- @broker4 = flexmock("broker_client4", :identity => @identity4, :usable? => true, :return_message => true,
443
- :alias => "b1", :host => "fourth", :port => 5672, :index => 1)
444
- @broker4.should_receive(:island_id).and_return(22)
445
- @broker4.should_receive(:in_home_island).and_return(true)
446
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity4, @address4, @serializer,
447
- @exceptions, Hash, @island2, nil).and_return(@broker4)
448
- end
449
-
450
- it "should convert identity into parts that includes island_id" do
451
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => 22)
452
- ha.identity_parts(@identity1).should == ["first", 5672, 0, 1, 11]
453
- ha.identity_parts(@identity2).should == ["second", 5672, 1, 0, 11]
454
- ha.identity_parts(@identity3).should == ["third", 5672, 0, 0, 22]
455
- ha.identity_parts(@identity4).should == ["fourth", 5672, 1, 1, 22]
456
- end
457
-
458
- it "should generate host:index list for home island" do
459
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => 22)
460
- ha.hosts.should == "third:0,fourth:1"
461
- ha.hosts(22).should == "third:0,fourth:1"
462
- end
463
-
464
- it "should generate host:index list for other island" do
465
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => 22)
466
- ha.hosts(11).should == "second:1,first:0"
467
- end
468
-
469
- it "should generate port:index list for home island" do
470
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => 22)
471
- ha.ports.should == "5672:0,5672:1"
472
- ha.ports(22).should == "5672:0,5672:1"
473
- end
474
-
475
- it "should generate port:index list for other island" do
476
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => 22)
477
- ha.ports(11).should == "5672:1,5672:0"
478
- end
479
-
480
- end # when using islands
481
-
482
- end # when identifying
483
-
484
- context "when" do
485
-
486
- before(:each) do
487
- @serializer = flexmock("Serializer")
488
- @exceptions = RightScale::StatsHelper::ExceptionStats
489
-
490
- @island1 = flexmock("island1", :id => 11, :index => 0, :broker_ports => nil)
491
- @island1.should_receive(:broker_hosts).and_return("first:0,second:1").by_default
492
- @island2 = flexmock("island2", :id => 22, :index => 1, :broker_ports => nil)
493
- @island2.should_receive(:broker_hosts).and_return("third:0,fourth:1").by_default
494
- @islands = {11 => @island1, 22 => @island2}
495
- @home = 22
496
-
497
- # Generate mocking for five BrokerClients in two islands with second being home island
498
- # The fifth client is not configured for use except when doing island updates
499
- # key index host alias island_id
500
- { 1 => [0, "first", "i0b0", 1],
501
- 2 => [1, "second", "i0b1", 1],
502
- 3 => [0, "third", "b0" , 2],
503
- 4 => [1, "fourth", "b1" , 2],
504
- 5 => [2, "fifth", "b2" , 2] }.each do |k, v|
505
- i, h, a, d = v
506
- eval("@identity#{k} = 'rs-broker-#{h}-5672'")
507
- eval("@address#{k} = {:host => '#{h}', :port => 5672, :index => #{i}}")
508
- eval("@broker#{k} = flexmock('broker_client#{k}', :identity => @identity#{k}, :alias => '#{a}', " +
509
- ":host => '#{h}', :port => 5672, :index => #{i}, :island_id => #{d}#{d}, " +
510
- ":in_home_island => #{d}#{d} == @home)")
511
- eval("@broker#{k}.should_receive(:status).and_return(:connected).by_default")
512
- eval("@broker#{k}.should_receive(:usable?).and_return(true).by_default")
513
- eval("@broker#{k}.should_receive(:connected?).and_return(true).by_default")
514
- eval("@broker#{k}.should_receive(:subscribe).and_return(true).by_default")
515
- eval("@broker#{k}.should_receive(:return_message).and_return(true).by_default")
516
- eval("flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity#{k}, @address#{k}, " +
517
- "@serializer, @exceptions, Hash, @island#{d}, nil).and_return(@broker#{k}).by_default")
518
- end
519
- end
520
-
521
- context "connecting" do
522
-
523
- # Generate mocking for three BrokerClients that do not use islands
524
- before(:each) do
525
- {0 => "a", 1 => "b", 2 => "c"}.each do |i, h|
526
- eval("@identity_#{h} = 'rs-broker-#{h}-5672'")
527
- eval("@address_#{h} = {:host => '#{h}', :port => 5672, :index => #{i}}")
528
- eval("@broker_#{h} = flexmock('broker_client_#{h}', :identity => @identity_#{h}, :alias => 'b#{i}', " +
529
- ":host => '#{h}', :port => 5672, :index => #{i}, :island_id => nil, " +
530
- ":in_home_island => true)")
531
- eval("@broker_#{h}.should_receive(:usable?).and_return(true).by_default")
532
- eval("@broker_#{h}.should_receive(:return_message).and_return(true).by_default")
533
- eval("flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity_#{h}, @address_#{h}, " +
534
- "@serializer, @exceptions, Hash, nil, any).and_return(@broker_#{h}).by_default")
535
- end
536
- end
537
-
538
- it "should connect and add a new broker client to the end of the list" do
539
- ha = RightScale::HABrokerClient.new(@serializer, :host => "a", :port => 5672)
540
- ha.brokers.size.should == 1
541
- ha.brokers[0].alias == "b0"
542
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity_b, @address_b, @serializer,
543
- @exceptions, Hash, nil, nil).and_return(@broker_b).once
544
- res = ha.connect("b", 5672, 1)
545
- res.should be_true
546
- ha.brokers.size.should == 2
547
- ha.brokers[1].alias == "b1"
548
- end
549
-
550
- it "should reconnect an existing broker client after closing it if it is not connected" do
551
- ha = RightScale::HABrokerClient.new(@serializer, :host => "a, b")
552
- ha.brokers.size.should == 2
553
- @broker_a.should_receive(:usable?).and_return(false)
554
- @broker_a.should_receive(:close).and_return(true).once
555
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity_a, @address_a, @serializer,
556
- @exceptions, Hash, nil, ha.brokers[0]).and_return(@broker_a).once
557
- res = ha.connect("a", 5672, 0)
558
- res.should be_true
559
- ha.brokers.size.should == 2
560
- ha.brokers[0].alias == "b0"
561
- ha.brokers[1].alias == "b1"
562
- end
563
-
564
- it "should a new broker client and reconnect broker clients when an island is specified" do
565
- ha = RightScale::HABrokerClient.new(@serializer, :islands => {22 => @island2}, :home_island => @home)
566
- ha.brokers.size.should == 2
567
- ha.brokers[0].alias == "b0"
568
- ha.brokers[1].alias == "b1"
569
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity2, @address2, @serializer,
570
- @exceptions, Hash, @island1, nil).and_return(@broker2).by_default
571
- res = ha.connect("second", 5672, 1, nil, @island1)
572
- res.should be_true
573
- ha.brokers.size.should == 3
574
- ha.brokers[0].alias == "b0"
575
- ha.brokers[1].alias == "b1"
576
- ha.brokers[2].alias == "i0b1"
577
- @broker3.should_receive(:usable?).and_return(false)
578
- @broker3.should_receive(:close).and_return(true).once
579
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity3, @address3, @serializer,
580
- @exceptions, Hash, @island2, ha.brokers[0]).and_return(@broker3).by_default
581
- res = ha.connect("third", 5672, 0, nil, @island2)
582
- res.should be_true
583
- ha.brokers.size.should == 3
584
- ha.brokers[0].alias == "b0"
585
- ha.brokers[1].alias == "b1"
586
- ha.brokers[2].alias == "i0b1"
587
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity1, @address1, @serializer,
588
- @exceptions, Hash, @island1, nil).and_return(@broker1).by_default
589
- res = ha.connect("first", 5672, 0, 0, @island1)
590
- res.should be_true
591
- ha.brokers.size.should == 4
592
- ha.brokers[0].alias == "b0"
593
- ha.brokers[1].alias == "b1"
594
- ha.brokers[2].alias == "i0b0"
595
- ha.brokers[3].alias == "i0b1"
596
- end
597
-
598
- it "should not do anything except log a message if asked to reconnect an already connected broker client" do
599
- @log.should_receive(:info).with(/Ignored request to reconnect/).once
600
- ha = RightScale::HABrokerClient.new(@serializer, :host => "a, b")
601
- ha.brokers.size.should == 2
602
- @broker_a.should_receive(:status).and_return(:connected).once
603
- @broker_a.should_receive(:close).and_return(true).never
604
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity_a, @address_a, @serializer,
605
- @exceptions, Hash, nil, ha.brokers[0]).and_return(@broker_a).never
606
- res = ha.connect("a", 5672, 0)
607
- res.should be_false
608
- ha.brokers.size.should == 2
609
- ha.brokers[0].alias == "b0"
610
- ha.brokers[1].alias == "b1"
611
- end
612
-
613
- it "should reconnect already connected broker client if force specified" do
614
- @log.should_receive(:info).with(/Ignored request to reconnect/).never
615
- ha = RightScale::HABrokerClient.new(@serializer, :host => "a, b")
616
- ha.brokers.size.should == 2
617
- @broker_a.should_receive(:close).and_return(true).once
618
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity_a, @address_a, @serializer,
619
- @exceptions, Hash, nil, ha.brokers[0]).and_return(@broker_a).once
620
- res = ha.connect("a", 5672, 0, nil, nil, force = true)
621
- res.should be_true
622
- ha.brokers.size.should == 2
623
- ha.brokers[0].alias == "b0"
624
- ha.brokers[1].alias == "b1"
625
- end
626
-
627
- it "should be able to change host and port of an existing broker client" do
628
- ha = RightScale::HABrokerClient.new(@serializer, :host => "a, b")
629
- ha.brokers.size.should == 2
630
- @broker_a.should_receive(:close).and_return(true).once
631
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity_c, @address_c.merge(:index => 0),
632
- @serializer, @exceptions, Hash, nil, nil).and_return(@broker_c).once
633
- res = ha.connect("c", 5672, 0)
634
- res.should be_true
635
- ha.brokers.size.should == 2
636
- ha.brokers[0].alias == "b0"
637
- ha.brokers[0].identity == @address_c
638
- ha.brokers[1].alias == "b1"
639
- ha.brokers[1].identity == @address_b
640
- end
641
-
642
- it "should slot broker client into specified priority position when at end of list" do
643
- ha = RightScale::HABrokerClient.new(@serializer, :host => "a, b")
644
- ha.brokers.size.should == 2
645
- res = ha.connect("c", 5672, 2, 2)
646
- res.should be_true
647
- ha.brokers.size.should == 3
648
- ha.brokers[0].alias == "b0"
649
- ha.brokers[1].alias == "b1"
650
- ha.brokers[2].alias == "b2"
651
- end
652
-
653
- it "should slot broker client into specified priority position when already is a client in that position" do
654
- ha = RightScale::HABrokerClient.new(@serializer, :host => "a, b")
655
- ha.brokers.size.should == 2
656
- res = ha.connect("c", 5672, 2, 1)
657
- res.should be_true
658
- ha.brokers.size.should == 3
659
- ha.brokers[0].alias == "b0"
660
- ha.brokers[1].alias == "b2"
661
- ha.brokers[2].alias == "b1"
662
- end
663
-
664
- it "should slot broker client into nex priority position if specified priority would leave a gap" do
665
- @log.should_receive(:info).with(/Reduced priority setting for broker/).once
666
- ha = RightScale::HABrokerClient.new(@serializer, :host => "a")
667
- ha.brokers.size.should == 1
668
- res = ha.connect("c", 5672, 2, 2)
669
- res.should be_true
670
- ha.brokers.size.should == 2
671
- ha.brokers[0].alias == "b0"
672
- ha.brokers[1].alias == "b2"
673
- end
674
-
675
- it "should yield to the block provided with the newly connected broker identity" do
676
- ha = RightScale::HABrokerClient.new(@serializer, :host => "a")
677
- ha.brokers.size.should == 1
678
- ha.brokers[0].alias == "b0"
679
- identity = nil
680
- res = ha.connect("b", 5672, 1) { |i| identity = i }
681
- res.should be_true
682
- identity.should == @identity_b
683
- ha.brokers.size.should == 2
684
- ha.brokers[1].alias == "b1"
685
- end
686
-
687
- end # connecting
688
-
689
- context "updating connection" do
690
-
691
- it "should connect to any brokers for which not currently connected and return their identity" do
692
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
693
- ha.brokers.size.should == 4
694
- @island2.should_receive(:broker_hosts).and_return("third:0,fourth:1,fifth:2")
695
- ha.connect_update(@islands)
696
- ha.brokers.size.should == 5
697
- ha.brokers[0].alias.should == "b0"
698
- ha.brokers[1].alias.should == "b1"
699
- ha.brokers[2].alias.should == "b2"
700
- ha.brokers[3].alias.should == "i0b0"
701
- ha.brokers[4].alias.should == "i0b1"
702
- ha.instance_variable_get(:@brokers_hash)[@identity5].should == @broker5
703
- end
704
-
705
- it "should do nothing if there is no change" do
706
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
707
- ha.brokers.size.should == 4
708
- ha.connect_update(@islands)
709
- ha.brokers.size.should == 4
710
- ha.brokers[0].alias.should == "b0"
711
- ha.brokers[1].alias.should == "b1"
712
- ha.brokers[2].alias.should == "i0b0"
713
- ha.brokers[3].alias.should == "i0b1"
714
- end
715
-
716
- it "should remove any broker clients for islands in which they are no longer configured" do
717
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
718
- ha.brokers.size.should == 4
719
- @broker1.should_receive(:close).and_return(true).once
720
- @broker3.should_receive(:close).and_return(true).once
721
- @island1.should_receive(:broker_hosts).and_return("second:1")
722
- @island2.should_receive(:broker_hosts).and_return("fourth:1,fifth:2")
723
- ha.connect_update(@islands)
724
- ha.brokers.size.should == 3
725
- ha.brokers[0].alias.should == "b2"
726
- ha.brokers[1].alias.should == "b1"
727
- ha.brokers[2].alias.should == "i0b1"
728
- ha.instance_variable_get(:@brokers_hash)[@identity1].should be_nil
729
- ha.instance_variable_get(:@brokers_hash)[@identity3].should be_nil
730
- ha.instance_variable_get(:@brokers_hash)[@identity5].should == @broker5
731
- end
732
-
733
- end # updating connection
734
-
735
- context "subscribing" do
736
-
737
- it "should subscribe on all usable broker clients and return their identities" do
738
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
739
- @broker1.should_receive(:usable?).and_return(false)
740
- @broker1.should_receive(:subscribe).never
741
- @broker2.should_receive(:subscribe).and_return(true).once
742
- @broker3.should_receive(:subscribe).and_return(true).once
743
- @broker4.should_receive(:subscribe).and_return(true).once
744
- result = ha.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"})
745
- result.should == [@identity3, @identity4, @identity2]
746
- end
747
-
748
- it "should not return the identity if subscribe fails" do
749
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
750
- @broker1.should_receive(:usable?).and_return(false)
751
- @broker1.should_receive(:subscribe).never
752
- @broker2.should_receive(:subscribe).and_return(true).once
753
- @broker3.should_receive(:subscribe).and_return(false).once
754
- @broker4.should_receive(:subscribe).and_return(true).once
755
- result = ha.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"})
756
- result.should == [@identity4, @identity2]
757
- end
758
-
759
- it "should subscribe only on specified brokers" do
760
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
761
- @broker1.should_receive(:usable?).and_return(false)
762
- @broker1.should_receive(:subscribe).never
763
- @broker2.should_receive(:subscribe).and_return(true).once
764
- @broker3.should_receive(:subscribe).never
765
- @broker4.should_receive(:subscribe).never
766
- result = ha.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"},
767
- :brokers => [@identity1, @identity2])
768
- result.should == [@identity2]
769
- end
770
-
771
- end # subscribing
772
-
773
- context "unsubscribing" do
774
-
775
- before(:each) do
776
- @timer = flexmock("timer", :cancel => true).by_default
777
- flexmock(EM::Timer).should_receive(:new).and_return(@timer).by_default
778
- @queue_name = "my_queue"
779
- @queue = flexmock("queue", :name => @queue_name)
780
- @queues = [@queue]
781
- @broker1.should_receive(:queues).and_return(@queues).by_default
782
- @broker1.should_receive(:unsubscribe).and_return(true).and_yield.by_default
783
- @broker2.should_receive(:queues).and_return(@queues).by_default
784
- @broker2.should_receive(:unsubscribe).and_return(true).and_yield.by_default
785
- @broker3.should_receive(:queues).and_return(@queues).by_default
786
- @broker3.should_receive(:unsubscribe).and_return(true).and_yield.by_default
787
- @broker4.should_receive(:queues).and_return(@queues).by_default
788
- @broker4.should_receive(:unsubscribe).and_return(true).and_yield.by_default
789
- end
790
-
791
- it "should unsubscribe from named queues on all usable broker clients" do
792
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
793
- @broker1.should_receive(:usable?).and_return(false)
794
- @broker1.should_receive(:unsubscribe).never
795
- @broker2.should_receive(:unsubscribe).and_return(true).once
796
- @broker3.should_receive(:unsubscribe).and_return(true).once
797
- @broker4.should_receive(:unsubscribe).and_return(true).once
798
- ha.unsubscribe([@queue_name]).should be_true
799
- end
800
-
801
- it "should yield to supplied block after unsubscribing" do
802
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
803
- ha.subscribe({:name => @queue_name}, {:type => :direct, :name => "exchange"})
804
- called = 0
805
- ha.unsubscribe([@queue_name]) { called += 1 }
806
- called.should == 1
807
- end
808
-
809
- it "should yield to supplied block if timeout before finish unsubscribing" do
810
- flexmock(EM::Timer).should_receive(:new).with(10, Proc).and_return(@timer).and_yield.once
811
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
812
- ha.subscribe({:name => @queue_name}, {:type => :direct, :name => "exchange"})
813
- called = 0
814
- ha.unsubscribe([@queue_name], 10) { called += 1 }
815
- called.should == 1
816
- end
817
-
818
- it "should cancel timer if finish unsubscribing before timer fires" do
819
- @timer.should_receive(:cancel).once
820
- flexmock(EM::Timer).should_receive(:new).with(10, Proc).and_return(@timer).once
821
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
822
- ha.subscribe({:name => @queue_name}, {:type => :direct, :name => "exchange"})
823
- called = 0
824
- ha.unsubscribe([@queue_name], 10) { called += 1 }
825
- called.should == 1
826
- end
827
-
828
- it "should yield to supplied block after unsubscribing even if no queues to unsubscribe" do
829
- @broker1.should_receive(:queues).and_return([])
830
- @broker2.should_receive(:queues).and_return([])
831
- @broker3.should_receive(:queues).and_return([])
832
- @broker4.should_receive(:queues).and_return([])
833
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
834
- called = 0
835
- ha.unsubscribe([@queue_name]) { called += 1 }
836
- called.should == 1
837
- end
838
-
839
- it "should yield to supplied block once after unsubscribing all queues" do
840
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
841
- ha.subscribe({:name => @queue_name}, {:type => :direct, :name => "exchange"})
842
- called = 0
843
- ha.unsubscribe([@queue_name]) { called += 1 }
844
- called.should == 1
845
- end
846
-
847
- end # unsubscribing
848
-
849
- context "declaring" do
850
-
851
- it "should declare exchange on all usable broker clients and return their identities" do
852
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
853
- @broker1.should_receive(:usable?).and_return(false)
854
- @broker1.should_receive(:declare).never
855
- @broker2.should_receive(:declare).and_return(true).once
856
- @broker3.should_receive(:declare).and_return(true).once
857
- @broker4.should_receive(:declare).and_return(true).once
858
- result = ha.declare(:exchange, "x", :durable => true)
859
- result.should == [@identity3, @identity4, @identity2]
860
- end
861
-
862
- it "should not return the identity if declare fails" do
863
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
864
- @broker1.should_receive(:usable?).and_return(false)
865
- @broker1.should_receive(:declare).never
866
- @broker2.should_receive(:declare).and_return(true).once
867
- @broker3.should_receive(:declare).and_return(false).once
868
- @broker4.should_receive(:declare).and_return(true).once
869
- result = ha.declare(:exchange, "x", :durable => true)
870
- result.should == [@identity4, @identity2]
871
- end
872
-
873
- it "should declare exchange only on specified brokers" do
874
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
875
- @broker1.should_receive(:usable?).and_return(false)
876
- @broker1.should_receive(:declare).never
877
- @broker2.should_receive(:declare).and_return(true).once
878
- @broker3.should_receive(:declare).never
879
- @broker4.should_receive(:declare).never
880
- result = ha.declare(:exchange, "x", :durable => true, :brokers => [@identity1, @identity2])
881
- result.should == [@identity2]
882
- end
883
-
884
- end # declaring
885
-
886
- context "publishing" do
887
-
888
- before(:each) do
889
- @message = flexmock("message")
890
- @packet = flexmock("packet", :class => RightScale::Request, :to_s => true, :version => [12, 12]).by_default
891
- @serializer.should_receive(:dump).with(@packet).and_return(@message).by_default
892
- @broker1.should_receive(:publish).and_return(true).by_default
893
- @broker2.should_receive(:publish).and_return(true).by_default
894
- @broker3.should_receive(:publish).and_return(true).by_default
895
- @broker4.should_receive(:publish).and_return(true).by_default
896
- end
897
-
898
- it "should serialize message, publish it, and return list of broker identifiers" do
899
- @serializer.should_receive(:dump).with(@packet).and_return(@message).once
900
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
901
- ha.publish({:type => :direct, :name => "exchange", :options => {:durable => true}},
902
- @packet, :persistent => true).should == [@identity3]
903
- end
904
-
905
- it "should try other broker clients if a publish fails" do
906
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
907
- @broker3.should_receive(:publish).and_return(false)
908
- ha.publish({:type => :direct, :name => "exchange"}, @packet).should == [@identity4]
909
- end
910
-
911
- it "should only try to use home island brokers by default" do
912
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
913
- @broker3.should_receive(:publish).and_return(false)
914
- @broker4.should_receive(:publish).and_return(false)
915
- lambda { ha.publish({:type => :direct, :name => "exchange"}, @packet) }.
916
- should raise_error(RightScale::HABrokerClient::NoConnectedBrokers)
917
- end
918
-
919
- it "should publish to a randomly selected broker if random requested" do
920
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
921
- srand(100)
922
- ha.publish({:type => :direct, :name => "exchange"}, @packet, :order => :random,
923
- :brokers =>[@identity1, @identity2, @identity3, @identity4]).should == [@identity2]
924
- end
925
-
926
- it "should publish to all connected brokers if fanout requested" do
927
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
928
- ha.publish({:type => :direct, :name => "exchange"}, @packet, :fanout => true,
929
- :brokers =>[@identity1, @identity2]).should == [@identity1, @identity2]
930
- end
931
-
932
- it "should publish only using specified brokers" do
933
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
934
- ha.publish({:type => :direct, :name => "exchange"}, @packet,
935
- :brokers =>[@identity1, @identity2]).should == [@identity1]
936
- end
937
-
938
- it "should log an error if a selected broker is unknown but still publish with any remaining brokers" do
939
- @log.should_receive(:error).with(/Invalid broker identity "rs-broker-fifth-5672"/).once
940
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
941
- ha.publish({:type => :direct, :name => "exchange"}, @packet,
942
- :brokers =>["rs-broker-fifth-5672", @identity1]).should == [@identity1]
943
- end
944
-
945
- it "should raise an exception if all available brokers fail to publish" do
946
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
947
- @broker3.should_receive(:publish).and_return(false)
948
- @broker4.should_receive(:publish).and_return(false)
949
- lambda { ha.publish({:type => :direct, :name => "exchange"}, @packet) }.
950
- should raise_error(RightScale::HABrokerClient::NoConnectedBrokers)
951
- end
952
-
953
- it "should not serialize the message if it is already serialized" do
954
- @serializer.should_receive(:dump).with(@packet).and_return(@message).never
955
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
956
- ha.publish({:type => :direct, :name => "exchange"}, @packet, :no_serialize => true).should == [@identity3]
957
- end
958
-
959
- it "should store message info for use by message returns if :mandatory specified" do
960
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
961
- ha.publish({:type => :direct, :name => "exchange"}, @packet, :mandatory => true).should == [@identity3]
962
- ha.instance_variable_get(:@published).instance_variable_get(:@cache).size.should == 1
963
- end
964
-
965
- it "should not store message info for use by message returns if message already serialized" do
966
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
967
- ha.publish({:type => :direct, :name => "exchange"}, @packet, :no_serialize => true).should == [@identity3]
968
- ha.instance_variable_get(:@published).instance_variable_get(:@cache).size.should == 0
969
- end
970
-
971
- it "should not store message info for use by message returns if mandatory not specified" do
972
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
973
- ha.publish({:type => :direct, :name => "exchange"}, @packet).should == [@identity3]
974
- ha.instance_variable_get(:@published).instance_variable_get(:@cache).size.should == 0
975
- end
976
-
977
- end # publishing
978
-
979
- context "returning" do
980
-
981
- before(:each) do
982
- @message = flexmock("message")
983
- @packet = flexmock("packet", :class => RightScale::Request, :to_s => true, :version => [12, 12]).by_default
984
- @serializer.should_receive(:dump).with(@packet).and_return(@message).by_default
985
- @broker1.should_receive(:publish).and_return(true).by_default
986
- @broker2.should_receive(:publish).and_return(true).by_default
987
- @broker3.should_receive(:publish).and_return(true).by_default
988
- @broker4.should_receive(:publish).and_return(true).by_default
989
- end
990
-
991
- it "should invoke return block" do
992
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
993
- @broker1.should_receive(:return_message).and_yield("exchange", "NO_CONSUMERS", @message).once
994
- called = 0
995
- ha.return_message do |id, reason, message, to, context|
996
- called += 1
997
- id.should == @identity1
998
- reason.should == "NO_CONSUMERS"
999
- message.should == @message
1000
- to.should == "exchange"
1001
- end
1002
- called.should == 1
1003
- end
1004
-
1005
- it "should record failure in message context if there is message context" do
1006
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1007
- ha.publish({:type => :direct, :name => "exchange", :options => {:durable => true}},
1008
- @packet, :mandatory => true).should == [@identity3]
1009
- @broker3.should_receive(:return_message).and_yield("exchange", "NO_CONSUMERS", @message).once
1010
- ha.return_message do |id, reason, message, to, context|
1011
- id.should == @identity3
1012
- reason.should == "NO_CONSUMERS"
1013
- message.should == @message
1014
- to.should == "exchange"
1015
- end
1016
- ha.instance_variable_get(:@published).fetch(@message).failed.should == [@identity3]
1017
- end
1018
-
1019
- context "when non-delivery" do
1020
-
1021
- it "should store non-delivery block for use by return handler" do
1022
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1023
- non_delivery = lambda {}
1024
- ha.non_delivery(&non_delivery)
1025
- ha.instance_variable_get(:@non_delivery).should == non_delivery
1026
- end
1027
-
1028
- end
1029
-
1030
- context "when handling return" do
1031
-
1032
- before(:each) do
1033
- @options = {}
1034
- @brokers = [@identity3, @identity4]
1035
- @context = RightScale::HABrokerClient::Context.new(@packet, @options, @brokers)
1036
- end
1037
-
1038
- it "should republish using a broker not yet tried if possible and log that re-routing" do
1039
- @log.should_receive(:info).with(/RE-ROUTE/).once
1040
- @log.should_receive(:info).with(/RETURN reason/).once
1041
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1042
- @context.record_failure(@identity3)
1043
- @broker4.should_receive(:publish).and_return(true).once
1044
- ha.__send__(:handle_return, @identity3, "reason", @message, "to", @context)
1045
- end
1046
-
1047
- it "should republish to same broker without mandatory if message is persistent and no other brokers available" do
1048
- @log.should_receive(:info).with(/RE-ROUTE/).once
1049
- @log.should_receive(:info).with(/RETURN reason/).once
1050
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1051
- @context.record_failure(@identity3)
1052
- @context.record_failure(@identity4)
1053
- @packet.should_receive(:persistent).and_return(true)
1054
- @broker3.should_receive(:publish).and_return(true).once
1055
- ha.__send__(:handle_return, @identity4, "NO_CONSUMERS", @message, "to", @context)
1056
- end
1057
-
1058
- it "should republish to same broker without mandatory if message is one-way and no other brokers available" do
1059
- @log.should_receive(:info).with(/RE-ROUTE/).once
1060
- @log.should_receive(:info).with(/RETURN reason/).once
1061
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1062
- @context.record_failure(@identity3)
1063
- @context.record_failure(@identity4)
1064
- @packet.should_receive(:one_way).and_return(true)
1065
- @broker3.should_receive(:publish).and_return(true).once
1066
- ha.__send__(:handle_return, @identity4, "NO_CONSUMERS", @message, "to", @context)
1067
- end
1068
-
1069
- it "should update status to :stopping if message returned because access refused" do
1070
- @log.should_receive(:info).with(/RE-ROUTE/).once
1071
- @log.should_receive(:info).with(/RETURN reason/).once
1072
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1073
- @context.record_failure(@identity3)
1074
- @broker4.should_receive(:publish).and_return(true).once
1075
- @broker3.should_receive(:update_status).with(:stopping).and_return(true).once
1076
- ha.__send__(:handle_return, @identity3, "ACCESS_REFUSED", @message, "to", @context)
1077
- end
1078
-
1079
- it "should log info and make non-delivery call even if persistent when returned because of no queue" do
1080
- @log.should_receive(:info).with(/NO ROUTE/).once
1081
- @log.should_receive(:info).with(/RETURN reason/).once
1082
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1083
- called = 0
1084
- ha.non_delivery { |reason, type, token, from, to| called += 1 }
1085
- @context.record_failure(@identity3)
1086
- @context.record_failure(@identity4)
1087
- @packet.should_receive(:persistent).and_return(true)
1088
- @broker3.should_receive(:publish).and_return(true).never
1089
- @broker4.should_receive(:publish).and_return(true).never
1090
- ha.__send__(:handle_return, @identity4, "NO_QUEUE", @message, "to", @context)
1091
- called.should == 1
1092
- end
1093
-
1094
- it "should log info and make non-delivery call if no route can be found" do
1095
- @log.should_receive(:info).with(/NO ROUTE/).once
1096
- @log.should_receive(:info).with(/RETURN reason/).once
1097
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1098
- called = 0
1099
- ha.non_delivery { |reason, type, token, from, to| called += 1 }
1100
- @context.record_failure(@identity3)
1101
- @context.record_failure(@identity4)
1102
- @broker3.should_receive(:publish).and_return(true).never
1103
- @broker4.should_receive(:publish).and_return(true).never
1104
- ha.__send__(:handle_return, @identity4, "any reason", @message, "to", @context)
1105
- called.should == 1
1106
- end
1107
-
1108
- it "should log info if no message context available for re-routing it" do
1109
- @log.should_receive(:info).with(/Dropping/).once
1110
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1111
- ha.__send__(:handle_return, @identity4, "any reason", @message, "to", nil)
1112
- end
1113
-
1114
- end
1115
-
1116
- end # returning
1117
-
1118
- context "deleting" do
1119
-
1120
- it "should delete queue on all usable broker clients and return their identities" do
1121
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1122
- @broker1.should_receive(:usable?).and_return(false)
1123
- @broker1.should_receive(:delete).never
1124
- @broker2.should_receive(:delete).and_return(true).once
1125
- @broker3.should_receive(:delete).and_return(true).once
1126
- @broker4.should_receive(:delete).and_return(true).once
1127
- ha.delete("queue").should == [@identity3, @identity4, @identity2]
1128
- end
1129
-
1130
- it "should not return the identity if delete fails" do
1131
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1132
- @broker1.should_receive(:usable?).and_return(false)
1133
- @broker1.should_receive(:delete).never
1134
- @broker2.should_receive(:delete).and_return(true).once
1135
- @broker3.should_receive(:delete).and_return(false).once
1136
- @broker4.should_receive(:delete).and_return(true).once
1137
- ha.delete("queue").should == [@identity4, @identity2]
1138
- end
1139
-
1140
- it "should delete queue from cache on all usable broker clients and return their identities" do
1141
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1142
- @broker1.should_receive(:usable?).and_return(false)
1143
- @broker1.should_receive(:delete_amqp_resources).never
1144
- @broker2.should_receive(:delete_amqp_resources).and_return(true).once
1145
- @broker3.should_receive(:delete_amqp_resources).and_return(true).once
1146
- @broker4.should_receive(:delete_amqp_resources).and_return(true).once
1147
- ha.delete_amqp_resources("queue").should == [@identity3, @identity4, @identity2]
1148
- end
1149
-
1150
- end # deleting
1151
-
1152
- context "removing" do
1153
-
1154
- it "should remove broker client after disconnecting and pass identity to block" do
1155
- @log.should_receive(:info).with(/Removing/).once
1156
- @broker2.should_receive(:close).with(true, true, false).once
1157
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1158
- identity = nil
1159
- result = ha.remove("second", 5672) { |i| identity = i }
1160
- result.should == @identity2
1161
- identity.should == @identity2
1162
- ha.get(@identity2).should be_nil
1163
- ha.get(@identity1).should_not be_nil
1164
- ha.get(@identity3).should_not be_nil
1165
- ha.get("rs-broker-fourth-5672").should_not be_nil
1166
- ha.brokers.size.should == 3
1167
- end
1168
-
1169
- it "should remove broker when no block supplied but still return a result" do
1170
- @log.should_receive(:info).with(/Removing/).once
1171
- @broker2.should_receive(:close).once
1172
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1173
- result = ha.remove("second", 5672)
1174
- result.should == @identity2
1175
- ha.get(@identity2).should be_nil
1176
- ha.get(@identity1).should_not be_nil
1177
- ha.get(@identity3).should_not be_nil
1178
- ha.get(@identity4).should_not be_nil
1179
- ha.brokers.size.should == 3
1180
- end
1181
-
1182
- it "should remove last broker if requested" do
1183
- @log.should_receive(:info).with(/Removing/).times(4)
1184
- @broker1.should_receive(:close).once
1185
- @broker2.should_receive(:close).once
1186
- @broker3.should_receive(:close).once
1187
- @broker4.should_receive(:close).once
1188
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1189
- result = ha.remove("second", 5672)
1190
- result.should == @identity2
1191
- ha.get(@identity2).should be_nil
1192
- result = ha.remove("third", 5672)
1193
- result.should == @identity3
1194
- ha.get(@identity3).should be_nil
1195
- result = ha.remove("fourth", 5672)
1196
- result.should == @identity4
1197
- ha.get(@identity4).should be_nil
1198
- ha.brokers.size.should == 1
1199
- identity = nil
1200
- result = ha.remove("first", 5672) { |i| identity = i }
1201
- result.should == @identity1
1202
- identity.should == @identity1
1203
- ha.get(@identity1).should be_nil
1204
- ha.brokers.size.should == 0
1205
- end
1206
-
1207
- it "should return nil and not execute block if broker is unknown" do
1208
- @log.should_receive(:info).with(/Ignored request to remove/).once
1209
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1210
- ha.remove("fifth", 5672).should be_nil
1211
- ha.brokers.size.should == 4
1212
- end
1213
-
1214
- it "should close connection and mark as failed when told broker is not usable" do
1215
- @broker2.should_receive(:close).with(true, false, false).once
1216
- @broker3.should_receive(:close).with(true, false, false).once
1217
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1218
- result = ha.declare_unusable([@identity2, @identity3])
1219
- ha.brokers.size.should == 4
1220
- end
1221
-
1222
- it "should raise an exception if broker that is declared not usable is unknown" do
1223
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1224
- lambda { ha.declare_unusable(["rs-broker-fifth-5672"]) }.should raise_error(Exception, /Cannot mark unknown/)
1225
- ha.brokers.size.should == 4
1226
- end
1227
-
1228
- end # removing
1229
-
1230
- context "monitoring" do
1231
-
1232
- include RightScale::StatsHelper
1233
-
1234
- before(:each) do
1235
- @timer = flexmock("timer")
1236
- flexmock(EM::Timer).should_receive(:new).and_return(@timer).by_default
1237
- @timer.should_receive(:cancel).by_default
1238
- @identity = "rs-broker-localhost-5672"
1239
- @address = {:host => "localhost", :port => 5672, :index => 0}
1240
- @broker = flexmock("broker_client", :identity => @identity, :alias => "b0", :host => "localhost",
1241
- :port => 5672, :index => 0, :island_id => nil, :in_home_island => true)
1242
- @broker.should_receive(:status).and_return(:connected).by_default
1243
- @broker.should_receive(:usable?).and_return(true).by_default
1244
- @broker.should_receive(:connected?).and_return(true).by_default
1245
- @broker.should_receive(:subscribe).and_return(true).by_default
1246
- @broker.should_receive(:return_message).and_return(true).by_default
1247
- flexmock(RightScale::BrokerClient).should_receive(:new).and_return(@broker).by_default
1248
- @broker1.should_receive(:failed?).and_return(false).by_default
1249
- @broker2.should_receive(:failed?).and_return(false).by_default
1250
- @broker3.should_receive(:failed?).and_return(false).by_default
1251
- @broker4.should_receive(:failed?).and_return(false).by_default
1252
- end
1253
-
1254
- it "should give access to or list usable brokers" do
1255
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1256
- aliases = []
1257
- res = ha.__send__(:each_usable) { |b| aliases << b.alias }
1258
- aliases.should == ["b0", "b1", "i0b0", "i0b1"]
1259
- res.size.should == 4
1260
- res[0].alias.should == "b0"
1261
- res[1].alias.should == "b1"
1262
- res[2].alias.should == "i0b0"
1263
- res[3].alias.should == "i0b1"
1264
-
1265
- @broker1.should_receive(:usable?).and_return(true)
1266
- @broker2.should_receive(:usable?).and_return(false)
1267
- @broker3.should_receive(:usable?).and_return(false)
1268
- @broker4.should_receive(:usable?).and_return(false)
1269
- aliases = []
1270
- res = ha.__send__(:each_usable) { |b| aliases << b.alias }
1271
- aliases.should == ["i0b0"]
1272
- res.size.should == 1
1273
- res[0].alias.should == "i0b0"
1274
- end
1275
-
1276
- it "should give list of unusable brokers" do
1277
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1278
- @broker1.should_receive(:usable?).and_return(true)
1279
- @broker2.should_receive(:usable?).and_return(false)
1280
- @broker3.should_receive(:usable?).and_return(false)
1281
- @broker4.should_receive(:usable?).and_return(true)
1282
- ha.unusable.should == [@identity3, @identity2]
1283
- end
1284
-
1285
- it "should give access to each selected usable broker" do
1286
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1287
- @broker2.should_receive(:usable?).and_return(true)
1288
- @broker3.should_receive(:usable?).and_return(false)
1289
- aliases = []
1290
- res = ha.__send__(:each_usable, [@identity2, @identity3]) { |b| aliases << b.alias }
1291
- aliases.should == ["i0b1"]
1292
- res.size.should == 1
1293
- res[0].alias.should == "i0b1"
1294
- end
1295
-
1296
- it "should tell whether a broker is connected" do
1297
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1298
- @broker2.should_receive(:connected?).and_return(false)
1299
- @broker3.should_receive(:connected?).and_return(true)
1300
- ha.connected?(@identity2).should be_false
1301
- ha.connected?(@identity3).should be_true
1302
- ha.connected?("rs-broker-fifth-5672").should be_nil
1303
- end
1304
-
1305
- it "should give list of connected brokers for home island by default" do
1306
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1307
- @broker1.should_receive(:connected?).and_return(true)
1308
- @broker2.should_receive(:connected?).and_return(false)
1309
- @broker3.should_receive(:connected?).and_return(true)
1310
- @broker4.should_receive(:connected?).and_return(false)
1311
- ha.connected.should == [@identity3]
1312
- end
1313
-
1314
- it "should give list of connected brokers for a specific island" do
1315
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1316
- @broker1.should_receive(:connected?).and_return(true)
1317
- @broker2.should_receive(:connected?).and_return(false)
1318
- @broker3.should_receive(:connected?).and_return(true)
1319
- @broker4.should_receive(:connected?).and_return(false)
1320
- ha.connected(11).should == [@identity1]
1321
- ha.connected(22).should == [@identity3]
1322
- end
1323
-
1324
- it "should give list of all brokers" do
1325
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1326
- ha.all.should == [@identity3, @identity4, @identity1, @identity2]
1327
- end
1328
-
1329
- it "should give list of failed brokers" do
1330
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1331
- @broker1.should_receive(:failed?).and_return(true)
1332
- @broker2.should_receive(:failed?).and_return(false)
1333
- @broker3.should_receive(:failed?).and_return(true)
1334
- @broker4.should_receive(:failed?).and_return(false)
1335
- ha.failed.should == [@identity3, @identity1]
1336
- end
1337
-
1338
- it "should give broker client status list" do
1339
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1340
- @broker1.should_receive(:summary).and_return("summary1")
1341
- @broker2.should_receive(:summary).and_return("summary2")
1342
- @broker3.should_receive(:summary).and_return("summary3")
1343
- @broker4.should_receive(:summary).and_return("summary4")
1344
- ha.status.should == ["summary3", "summary4", "summary1", "summary2"]
1345
- end
1346
-
1347
- it "should give broker client statistics" do
1348
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1349
- @broker1.should_receive(:stats).and_return("stats1")
1350
- @broker2.should_receive(:stats).and_return("stats2")
1351
- @broker3.should_receive(:stats).and_return("stats3")
1352
- @broker4.should_receive(:stats).and_return("stats4")
1353
- ha.stats.should == {"brokers" => ["stats3", "stats4", "stats1", "stats2"],
1354
- "exceptions" => nil,
1355
- "heartbeat" => nil,
1356
- "returns" => nil}
1357
- end
1358
-
1359
- it "should log broker client status update if there is a change" do
1360
- @log.should_receive(:info).with(/Broker b0 is now connected/).once
1361
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1362
- ha.__send__(:update_status, @broker3, false)
1363
- end
1364
-
1365
- it "should not log broker client status update if there is no change" do
1366
- @log.should_receive(:info).with(/Broker b0 is now connected/).never
1367
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1368
- ha.__send__(:update_status, @broker3, true)
1369
- end
1370
-
1371
- it "should log broker client status update when become disconnected" do
1372
- @log.should_receive(:info).with(/Broker b0 is now disconnected/).once
1373
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1374
- @broker3.should_receive(:status).and_return(:disconnected)
1375
- @broker3.should_receive(:connected?).and_return(false)
1376
- ha.__send__(:update_status, @broker3, true)
1377
- end
1378
-
1379
- it "should provide connection status callback when cross 0/1 connection boundary for home island" do
1380
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1381
- connected = 0
1382
- disconnected = 0
1383
- ha.connection_status do |status|
1384
- if status == :connected
1385
- (ha.brokers[0].status == :connected ||
1386
- ha.brokers[1].status == :connected).should be_true
1387
- connected += 1
1388
- elsif status == :disconnected
1389
- (ha.brokers[0].status == :disconnected &&
1390
- ha.brokers[1].status == :disconnected).should be_true
1391
- disconnected += 1
1392
- end
1393
- end
1394
- ha.__send__(:update_status, @broker3, false)
1395
- connected.should == 0
1396
- disconnected.should == 0
1397
- @broker3.should_receive(:status).and_return(:disconnected)
1398
- @broker3.should_receive(:connected?).and_return(false)
1399
- ha.__send__(:update_status, @broker3, true)
1400
- connected.should == 0
1401
- disconnected.should == 0
1402
- @broker4.should_receive(:status).and_return(:disconnected)
1403
- @broker4.should_receive(:connected?).and_return(false)
1404
- ha.__send__(:update_status, @broker4, true)
1405
- connected.should == 0
1406
- disconnected.should == 1
1407
- # TODO fix this test so that also checks crossing boundary as become connected
1408
- end
1409
-
1410
- it "should provide connection status callback when cross n/n-1 connection boundary for home island when all specified" do
1411
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1412
- connected = 0
1413
- disconnected = 0
1414
- ha.connection_status(:boundary => :all) do |status|
1415
- if status == :connected
1416
- (ha.brokers[0].status == :connected &&
1417
- ha.brokers[1].status == :connected).should be_true
1418
- connected += 1
1419
- elsif status == :disconnected
1420
- (ha.brokers[0].status == :disconnected ||
1421
- ha.brokers[1].status == :disconnected).should be_true
1422
- disconnected += 1
1423
- end
1424
- end
1425
- ha.__send__(:update_status, @broker3, false)
1426
- connected.should == 1
1427
- disconnected.should == 0
1428
- @broker3.should_receive(:status).and_return(:disconnected)
1429
- @broker3.should_receive(:connected?).and_return(false)
1430
- ha.__send__(:update_status, @broker3, true)
1431
- connected.should == 1
1432
- disconnected.should == 1
1433
- @broker4.should_receive(:status).and_return(:disconnected)
1434
- @broker4.should_receive(:connected?).and_return(false)
1435
- ha.__send__(:update_status, @broker4, true)
1436
- connected.should == 1
1437
- disconnected.should == 1
1438
- # TODO fix this test so that also checks crossing boundary as become disconnected
1439
- end
1440
-
1441
- it "should provide connection status callback when cross connection boundary for non-home island" do
1442
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1443
- @broker1.should_receive(:island_alias).and_return(:i0)
1444
- @broker2.should_receive(:island_alias).and_return(:i0)
1445
- connected = 0
1446
- disconnected = 0
1447
- ha.connection_status do |status|
1448
- if status == :connected
1449
- (ha.brokers[2].status == :connected ||
1450
- ha.brokers[3].status == :connected).should be_true
1451
- connected += 1
1452
- elsif status == :disconnected
1453
- (ha.brokers[2].status == :disconnected &&
1454
- ha.brokers[3].status == :disconnected).should be_true
1455
- disconnected += 1
1456
- end
1457
- end
1458
- ha.__send__(:update_status, @broker1, false)
1459
- connected.should == 0
1460
- disconnected.should == 0
1461
- @broker1.should_receive(:status).and_return(:disconnected)
1462
- @broker1.should_receive(:connected?).and_return(false)
1463
- ha.__send__(:update_status, @broker1, true)
1464
- connected.should == 0
1465
- disconnected.should == 0
1466
- @broker2.should_receive(:status).and_return(:disconnected)
1467
- @broker2.should_receive(:connected?).and_return(false)
1468
- ha.__send__(:update_status, @broker2, true)
1469
- connected.should == 0
1470
- disconnected.should == 1
1471
- end
1472
-
1473
- it "should provide connection status callback for specific broker set" do
1474
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1475
- @broker1.should_receive(:island_alias).and_return(:i0)
1476
- @broker2.should_receive(:island_alias).and_return(:i0)
1477
- connected = 0
1478
- disconnected = 0
1479
- ha.connection_status(:brokers => [@identity1, @identity2]) do |status|
1480
- if status == :connected
1481
- (ha.brokers[2].status == :connected ||
1482
- ha.brokers[3].status == :connected).should be_true
1483
- connected += 1
1484
- elsif status == :disconnected
1485
- (ha.brokers[2].status == :disconnected &&
1486
- ha.brokers[3].status == :disconnected).should be_true
1487
- disconnected += 1
1488
- end
1489
- end
1490
- ha.__send__(:update_status, @broker1, false)
1491
- connected.should == 0
1492
- disconnected.should == 0
1493
- @broker1.should_receive(:status).and_return(:disconnected)
1494
- @broker1.should_receive(:connected?).and_return(false)
1495
- ha.__send__(:update_status, @broker1, true)
1496
- connected.should == 0
1497
- disconnected.should == 0
1498
- @broker2.should_receive(:status).and_return(:disconnected)
1499
- @broker2.should_receive(:connected?).and_return(false)
1500
- ha.__send__(:update_status, @broker2, true)
1501
- connected.should == 0
1502
- disconnected.should == 1
1503
- end
1504
-
1505
- it "should provide connection status callback only once when one-off is requested" do
1506
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity, @address, @serializer,
1507
- @exceptions, Hash, nil, nil).and_return(@broker).once
1508
- ha = RightScale::HABrokerClient.new(@serializer)
1509
- called = 0
1510
- ha.connection_status(:one_off => 10) { |_| called += 1 }
1511
- ha.__send__(:update_status, @broker, false)
1512
- called.should == 1
1513
- @broker.should_receive(:status).and_return(:disconnected)
1514
- @broker.should_receive(:connected?).and_return(false)
1515
- ha.__send__(:update_status, @broker, true)
1516
- called.should == 1
1517
- end
1518
-
1519
- it "should use connection status timer when one-off is requested" do
1520
- flexmock(EM::Timer).should_receive(:new).and_return(@timer).once
1521
- @timer.should_receive(:cancel).once
1522
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity, @address, @serializer,
1523
- @exceptions, Hash, nil, nil).and_return(@broker).once
1524
- ha = RightScale::HABrokerClient.new(@serializer)
1525
- called = 0
1526
- ha.connection_status(:one_off => 10) { |_| called += 1 }
1527
- ha.__send__(:update_status, @broker, false)
1528
- called.should == 1
1529
- end
1530
-
1531
- it "should give timeout connection status if one-off request times out" do
1532
- flexmock(EM::Timer).should_receive(:new).and_return(@timer).and_yield.once
1533
- @timer.should_receive(:cancel).never
1534
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity, @address, @serializer,
1535
- @exceptions, Hash, nil, nil).and_return(@broker).once
1536
- ha = RightScale::HABrokerClient.new(@serializer)
1537
- called = 0
1538
- ha.connection_status(:one_off => 10) { |status| called += 1; status.should == :timeout }
1539
- called.should == 1
1540
- end
1541
-
1542
- it "should be able to have multiple connection status callbacks" do
1543
- flexmock(RightScale::BrokerClient).should_receive(:new).with(@identity, @address, @serializer,
1544
- @exceptions, Hash, nil, nil).and_return(@broker).once
1545
- ha = RightScale::HABrokerClient.new(@serializer)
1546
- called1 = 0
1547
- called2 = 0
1548
- ha.connection_status(:one_off => 10) { |_| called1 += 1 }
1549
- ha.connection_status(:boundary => :all) { |_| called2 += 1 }
1550
- ha.__send__(:update_status, @broker, false)
1551
- @broker.should_receive(:status).and_return(:disconnected)
1552
- @broker.should_receive(:connected?).and_return(false)
1553
- ha.__send__(:update_status, @broker, true)
1554
- called1.should == 1
1555
- called2.should == 2
1556
- end
1557
-
1558
- it "should provide failed connection status callback when all brokers fail to connect" do
1559
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1560
- connected = disconnected = failed = 0
1561
- ha.connection_status(:boundary => :all) do |status|
1562
- if status == :connected
1563
- connected += 1
1564
- elsif status == :disconnected
1565
- disconnected += 1
1566
- elsif status == :failed
1567
- (ha.brokers[0].failed? &&
1568
- ha.brokers[1].failed? &&
1569
- ha.brokers[2].failed? &&
1570
- ha.brokers[3].failed?).should be_true
1571
- failed += 1
1572
- end
1573
- end
1574
- @broker1.should_receive(:failed?).and_return(true)
1575
- @broker1.should_receive(:connected?).and_return(false)
1576
- ha.__send__(:update_status, @broker1, false)
1577
- connected.should == 0
1578
- disconnected.should == 0
1579
- failed.should == 0
1580
- @broker2.should_receive(:failed?).and_return(true)
1581
- @broker2.should_receive(:connected?).and_return(false)
1582
- ha.__send__(:update_status, @broker2, false)
1583
- connected.should == 0
1584
- disconnected.should == 0
1585
- failed.should == 0
1586
- @broker3.should_receive(:failed?).and_return(true)
1587
- @broker3.should_receive(:connected?).and_return(false)
1588
- ha.__send__(:update_status, @broker3, false)
1589
- connected.should == 0
1590
- disconnected.should == 0
1591
- failed.should == 0
1592
- @broker4.should_receive(:failed?).and_return(true)
1593
- @broker4.should_receive(:connected?).and_return(false)
1594
- ha.__send__(:update_status, @broker4, false)
1595
- connected.should == 0
1596
- disconnected.should == 0
1597
- failed.should == 1
1598
- end
1599
-
1600
- it "should provide failed connection status callback when brokers selected and all brokers fail to connect" do
1601
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1602
- connected = disconnected = failed = 0
1603
- ha.connection_status(:boundary => :all, :brokers => [@broker3.identity, @broker4.identity]) do |status|
1604
- if status == :connected
1605
- connected += 1
1606
- elsif status == :disconnected
1607
- disconnected += 1
1608
- elsif status == :failed
1609
- (ha.brokers[0].failed? &&
1610
- ha.brokers[1].failed?).should be_true
1611
- failed += 1
1612
- end
1613
- end
1614
- @broker1.should_receive(:failed?).and_return(true)
1615
- @broker2.should_receive(:failed?).and_return(true)
1616
- @broker3.should_receive(:failed?).and_return(true)
1617
- @broker3.should_receive(:connected?).and_return(false)
1618
- ha.__send__(:update_status, @broker3, false)
1619
- connected.should == 0
1620
- disconnected.should == 0
1621
- failed.should == 0
1622
- @broker4.should_receive(:failed?).and_return(true)
1623
- @broker4.should_receive(:connected?).and_return(false)
1624
- ha.__send__(:update_status, @broker4, false)
1625
- connected.should == 0
1626
- disconnected.should == 0
1627
- failed.should == 1
1628
- end
1629
-
1630
- end # monitoring
1631
-
1632
- context "closing" do
1633
-
1634
- it "should close all broker connections and execute block after all connections are closed" do
1635
- @broker1.should_receive(:close).with(false, Proc).and_return(true).and_yield.once
1636
- @broker2.should_receive(:close).with(false, Proc).and_return(true).and_yield.once
1637
- @broker3.should_receive(:close).with(false, Proc).and_return(true).and_yield.once
1638
- @broker4.should_receive(:close).with(false, Proc).and_return(true).and_yield.once
1639
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1640
- called = 0
1641
- ha.close { called += 1 }
1642
- called.should == 1
1643
- end
1644
-
1645
- it "should close broker connections when no block supplied" do
1646
- @broker1.should_receive(:close).with(false, Proc).and_return(true).and_yield.once
1647
- @broker2.should_receive(:close).with(false, Proc).and_return(true).and_yield.once
1648
- @broker3.should_receive(:close).with(false, Proc).and_return(true).and_yield.once
1649
- @broker4.should_receive(:close).with(false, Proc).and_return(true).and_yield.once
1650
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1651
- ha.close
1652
- end
1653
-
1654
- it "should close all broker connections even if encounter an exception" do
1655
- @log.should_receive(:error).with(/Failed to close/, Exception, :trace).once
1656
- @broker1.should_receive(:close).and_return(true).and_yield.once
1657
- @broker2.should_receive(:close).and_raise(Exception).once
1658
- @broker3.should_receive(:close).and_return(true).and_yield.once
1659
- @broker4.should_receive(:close).and_return(true).and_yield.once
1660
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1661
- called = 0
1662
- ha.close { called += 1 }
1663
- called.should == 1
1664
- end
1665
-
1666
- it "should close an individual broker connection" do
1667
- @broker1.should_receive(:close).with(true).and_return(true).once
1668
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1669
- ha.close_one(@identity1)
1670
- end
1671
-
1672
- it "should not propagate connection status change if requested not to" do
1673
- @broker1.should_receive(:close).with(false).and_return(true).once
1674
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1675
- ha.close_one(@identity1, propagate = false)
1676
- end
1677
-
1678
- it "should close an individual broker connection and execute block if given" do
1679
- @broker1.should_receive(:close).with(true, Proc).and_return(true).and_yield.once
1680
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1681
- called = 0
1682
- ha.close_one(@identity1) { called += 1 }
1683
- called.should == 1
1684
- end
1685
-
1686
- it "should raise exception if unknown broker" do
1687
- ha = RightScale::HABrokerClient.new(@serializer, :islands => @islands, :home_island => @home)
1688
- lambda { ha.close_one("rs-broker-fifth-5672") }.should raise_error(Exception, /Cannot close unknown broker/)
1689
- end
1690
-
1691
- end # closing
1692
-
1693
- end # when
1694
-
1695
- end # RightScale::HABrokerClient