right_agent 0.6.6 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
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