right_agent 0.5.1 → 0.5.10
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/right_agent.rb +3 -13
- data/lib/right_agent/actors/agent_manager.rb +78 -4
- data/lib/right_agent/agent.rb +81 -4
- data/lib/right_agent/agent_config.rb +17 -1
- data/lib/right_agent/agent_tags_manager.rb +2 -2
- data/lib/right_agent/broker_client.rb +32 -34
- data/lib/right_agent/command/agent_manager_commands.rb +16 -0
- data/lib/right_agent/command/command_constants.rb +0 -9
- data/lib/right_agent/dispatcher.rb +6 -3
- data/lib/right_agent/ha_broker_client.rb +63 -14
- data/lib/right_agent/log.rb +1 -1
- data/lib/right_agent/minimal.rb +43 -0
- data/lib/right_agent/monkey_patches/amqp_patch.rb +91 -182
- data/lib/right_agent/packets.rb +10 -5
- data/lib/right_agent/platform.rb +8 -0
- data/lib/right_agent/platform/darwin.rb +14 -0
- data/lib/right_agent/platform/linux.rb +23 -0
- data/lib/right_agent/platform/windows.rb +31 -0
- data/lib/right_agent/scripts/agent_controller.rb +16 -8
- data/lib/right_agent/scripts/agent_deployer.rb +6 -0
- data/lib/right_agent/scripts/log_level_manager.rb +4 -5
- data/lib/right_agent/scripts/stats_manager.rb +9 -1
- data/lib/right_agent/sender.rb +623 -371
- data/lib/right_agent/stats_helper.rb +15 -1
- data/lib/right_agent/tracer.rb +1 -1
- data/right_agent.gemspec +14 -15
- data/spec/agent_config_spec.rb +9 -0
- data/spec/agent_spec.rb +154 -18
- data/spec/broker_client_spec.rb +171 -170
- data/spec/dispatcher_spec.rb +24 -8
- data/spec/ha_broker_client_spec.rb +55 -33
- data/spec/monkey_patches/amqp_patch_spec.rb +12 -0
- data/spec/packets_spec.rb +2 -0
- data/spec/sender_spec.rb +140 -69
- data/spec/stats_helper_spec.rb +5 -0
- metadata +54 -53
data/lib/right_agent.rb
CHANGED
@@ -20,31 +20,22 @@
|
|
20
20
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
22
|
|
23
|
-
|
23
|
+
# reuse minimal loader to ensure right_agent can safely be required after minimal.
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_agent', 'minimal'))
|
25
|
+
|
24
26
|
require 'amqp'
|
25
|
-
require 'mq'
|
26
27
|
require 'json'
|
27
28
|
require 'yaml'
|
28
29
|
require 'openssl'
|
29
30
|
|
30
|
-
# Cannot use File.normalize_path here because not defined until after this include
|
31
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'right_agent', 'platform'))
|
32
|
-
|
33
|
-
unless defined?(RIGHT_AGENT_BASE_DIR)
|
34
|
-
RIGHT_AGENT_BASE_DIR = File.normalize_path(File.join(File.dirname(__FILE__), 'right_agent'))
|
35
|
-
end
|
36
|
-
|
37
31
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'monkey_patches'))
|
38
|
-
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'agent_config'))
|
39
32
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'payload_formatter'))
|
40
33
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'packets'))
|
41
34
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'enrollment_result'))
|
42
35
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'console'))
|
43
36
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'daemonize'))
|
44
|
-
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'pid_file'))
|
45
37
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'exceptions'))
|
46
38
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'multiplexer'))
|
47
|
-
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'log'))
|
48
39
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'tracer'))
|
49
40
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'audit_formatter'))
|
50
41
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'serialize'))
|
@@ -54,7 +45,6 @@ require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'subprocess'))
|
|
54
45
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'stats_helper'))
|
55
46
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'broker_client'))
|
56
47
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'ha_broker_client'))
|
57
|
-
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'command'))
|
58
48
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'agent_identity'))
|
59
49
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'agent_tags_manager'))
|
60
50
|
require File.normalize_path(File.join(RIGHT_AGENT_BASE_DIR, 'actor'))
|
@@ -30,7 +30,8 @@ class AgentManager
|
|
30
30
|
|
31
31
|
on_exception { |meth, deliverable, e| RightScale::ExceptionMailer.deliver_notification(meth, deliverable, e) }
|
32
32
|
|
33
|
-
expose :ping, :stats, :set_log_level, :execute, :connect, :disconnect, :
|
33
|
+
expose :ping, :stats, :profile, :set_log_level, :execute, :connect, :disconnect, :connect_failed,
|
34
|
+
:tune_heartbeat, :terminate
|
34
35
|
|
35
36
|
# Valid log levels
|
36
37
|
LEVELS = [:debug, :info, :warn, :error, :fatal]
|
@@ -68,6 +69,48 @@ class AgentManager
|
|
68
69
|
@agent.stats(RightScale::SerializationHelper.symbolize_keys(options))
|
69
70
|
end
|
70
71
|
|
72
|
+
# Profile memory use
|
73
|
+
#
|
74
|
+
# === Parameters
|
75
|
+
# options(Hash):: Request options
|
76
|
+
# :start(Boolean):: Whether to start profiling
|
77
|
+
# :stats(Boolean):: Whether to display profile statistics to stdout
|
78
|
+
# :reset(Boolean):: Whether to reset profile statistics when after displaying them
|
79
|
+
# :stop(Boolean):: Whether to stop profiling
|
80
|
+
#
|
81
|
+
# === Return
|
82
|
+
# (OperationResult):: Empty success result or error result with message
|
83
|
+
def profile(options)
|
84
|
+
require 'memprof'
|
85
|
+
|
86
|
+
options = RightScale::SerializationHelper.symbolize_keys(options)
|
87
|
+
if options[:start]
|
88
|
+
RightScale::Log.info("[profile] Start")
|
89
|
+
$stderr.puts "[profile] Start at #{Time.now}"
|
90
|
+
Memprof.start
|
91
|
+
@profiling = true
|
92
|
+
end
|
93
|
+
|
94
|
+
if options[:stats]
|
95
|
+
return error_result("Profiling has not yet been started") unless @profiling
|
96
|
+
RightScale::Log.info("[profile] GC start")
|
97
|
+
$stderr.puts "[profile] GC at #{Time.now}"
|
98
|
+
GC.start
|
99
|
+
RightScale::Log.info("[profile] Display stats to stderr")
|
100
|
+
$stderr.puts "[profile] Stats at #{Time.now}#{options[:reset] ? ' with reset' : ''}"
|
101
|
+
options[:reset] ? Memprof.stats! : Memprof.stats
|
102
|
+
end
|
103
|
+
|
104
|
+
if options[:stop]
|
105
|
+
return error_result("Profiling has not yet been started") unless @profiling
|
106
|
+
RightScale::Log.info("[profile] Stop")
|
107
|
+
$stderr.puts "[profile] Stop at #{Time.now}"
|
108
|
+
Memprof.stop
|
109
|
+
@profiling = false
|
110
|
+
end
|
111
|
+
success_result
|
112
|
+
end
|
113
|
+
|
71
114
|
# Change log level of agent
|
72
115
|
#
|
73
116
|
# === Parameter
|
@@ -123,7 +166,7 @@ class AgentManager
|
|
123
166
|
res = error_result(error)
|
124
167
|
end
|
125
168
|
rescue Exception => e
|
126
|
-
res = error_result("Failed to connect to broker
|
169
|
+
res = error_result("Failed to connect to broker", e)
|
127
170
|
end
|
128
171
|
res
|
129
172
|
end
|
@@ -146,7 +189,7 @@ class AgentManager
|
|
146
189
|
res = error_result(error)
|
147
190
|
end
|
148
191
|
rescue Exception => e
|
149
|
-
res = error_result("Failed to disconnect from broker
|
192
|
+
res = error_result("Failed to disconnect from broker", e)
|
150
193
|
end
|
151
194
|
res
|
152
195
|
end
|
@@ -167,7 +210,38 @@ class AgentManager
|
|
167
210
|
res = error_result(error)
|
168
211
|
end
|
169
212
|
rescue Exception => e
|
170
|
-
res = error_result("Failed to notify agent that brokers #{options[:brokers]} are unusable
|
213
|
+
res = error_result("Failed to notify agent that brokers #{options[:brokers]} are unusable", e)
|
214
|
+
end
|
215
|
+
res
|
216
|
+
end
|
217
|
+
|
218
|
+
# Tune connection heartbeat frequency for all brokers
|
219
|
+
# Any response to this request is not likely to get through if :immediate is specified
|
220
|
+
# because the broker connections will be in flux
|
221
|
+
# Use of :immediate should be avoided when this is a fanned out request to avoid
|
222
|
+
# overloading the brokers
|
223
|
+
#
|
224
|
+
# === Parameters
|
225
|
+
# options(Hash):: Tune options:
|
226
|
+
# :heartbeat(Integer):: New AMQP connection heartbeat setting, nil or 0 means disable
|
227
|
+
# :immediate(Boolean):: Whether to tune heartbeat immediately rather than defer until next
|
228
|
+
# status check
|
229
|
+
#
|
230
|
+
# === Return
|
231
|
+
# res(RightScale::OperationResult):: Success unless exception is raised
|
232
|
+
def tune_heartbeat(options)
|
233
|
+
options = RightScale::SerializationHelper.symbolize_keys(options)
|
234
|
+
res = success_result
|
235
|
+
begin
|
236
|
+
if options[:immediate]
|
237
|
+
if error = @agent.tune_heartbeat(options[:heartbeat])
|
238
|
+
res = error_result(error)
|
239
|
+
end
|
240
|
+
else
|
241
|
+
@agent.defer_task { @agent.tune_heartbeat(options[:heartbeat]) }
|
242
|
+
end
|
243
|
+
rescue Exception => e
|
244
|
+
res = error_result("Failed to tune heartbeat", e)
|
171
245
|
end
|
172
246
|
res
|
173
247
|
end
|
data/lib/right_agent/agent.rb
CHANGED
@@ -73,6 +73,7 @@ module RightScale
|
|
73
73
|
:check_interval => 5 * 60,
|
74
74
|
:grace_timeout => 30,
|
75
75
|
:prefetch => 1,
|
76
|
+
:heartbeat => 60
|
76
77
|
}
|
77
78
|
|
78
79
|
# Initializes a new agent and establishes an AMQP connection.
|
@@ -97,12 +98,14 @@ module RightScale
|
|
97
98
|
# :retry_timeout(Numeric):: Maximum number of seconds to retry request before give up
|
98
99
|
# :time_to_live(Integer):: Number of seconds before a request expires and is to be ignored
|
99
100
|
# by the receiver, 0 means never expire, defaults to 0
|
100
|
-
# :connect_timeout:: Number of seconds to wait for a broker connection to be established
|
101
|
+
# :connect_timeout(Integer):: Number of seconds to wait for a broker connection to be established
|
101
102
|
# :reconnect_interval(Integer):: Number of seconds between broker reconnect attempts
|
102
103
|
# :ping_interval(Integer):: Minimum number of seconds since last message receipt to ping the mapper
|
103
104
|
# to check connectivity, defaults to 0 meaning do not ping
|
104
|
-
# :check_interval:: Number of seconds between publishing stats and checking for broker connections
|
105
|
+
# :check_interval(Integer):: Number of seconds between publishing stats and checking for broker connections
|
105
106
|
# that failed during agent launch and then attempting to reconnect via the mapper
|
107
|
+
# :heartbeat(Integer):: Number of seconds between AMQP connection heartbeats used to keep
|
108
|
+
# connection alive (e.g., when AMQP broker is behind a firewall), nil or 0 means disable
|
106
109
|
# :grace_timeout(Integer):: Maximum number of seconds to wait after last request received before
|
107
110
|
# terminating regardless of whether there are still unfinished requests
|
108
111
|
# :dup_check(Boolean):: Whether to check for and reject duplicate requests, e.g., due to retries
|
@@ -153,6 +156,7 @@ module RightScale
|
|
153
156
|
@tags << opts[:tag] if opts[:tag]
|
154
157
|
@tags.flatten!
|
155
158
|
@options.freeze
|
159
|
+
@deferred_tasks = []
|
156
160
|
@terminating = false
|
157
161
|
@last_stat_reset_time = @service_start_time = Time.now
|
158
162
|
reset_agent_stats
|
@@ -239,6 +243,57 @@ module RightScale
|
|
239
243
|
@registry.register(actor, prefix)
|
240
244
|
end
|
241
245
|
|
246
|
+
# Tune connection heartbeat frequency for all brokers
|
247
|
+
# Causes a reconnect to each broker
|
248
|
+
#
|
249
|
+
# === Parameters
|
250
|
+
# heartbeat(Integer):: Number of seconds between AMQP connection heartbeats used to keep
|
251
|
+
# connection alive (e.g., when AMQP broker is behind a firewall), nil or 0 means disable
|
252
|
+
#
|
253
|
+
# === Return
|
254
|
+
# res(String|nil):: Error message if failed, otherwise nil
|
255
|
+
def tune_heartbeat(heartbeat)
|
256
|
+
res = nil
|
257
|
+
begin
|
258
|
+
@broker.heartbeat = heartbeat
|
259
|
+
update_configuration(:heartbeat => heartbeat)
|
260
|
+
ids = []
|
261
|
+
all = @broker.all
|
262
|
+
all.each do |id|
|
263
|
+
begin
|
264
|
+
host, port, index, priority, island_id = @broker.identity_parts(id)
|
265
|
+
@broker.connect(host, port, index, priority, island = nil, force = true) do |id|
|
266
|
+
@broker.connection_status(:one_off => @options[:connect_timeout], :brokers => [id]) do |status|
|
267
|
+
begin
|
268
|
+
if status == :connected
|
269
|
+
setup_queues([id])
|
270
|
+
tuned = (heartbeat && heartbeat != 0) ? "Tuned heartbeat to #{heartbeat} seconds" : "Disabled heartbeat"
|
271
|
+
Log.info("[setup] #{tuned} for broker #{id}")
|
272
|
+
else
|
273
|
+
Log.error("Failed to reconnect to broker #{id} to tune heartbeat, status #{status.inspect}")
|
274
|
+
end
|
275
|
+
rescue Exception => e
|
276
|
+
Log.error("Failed to setup queues for broker #{id} when tuning heartbeat", e, :trace)
|
277
|
+
@exceptions.track("tune heartbeat", e)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
ids << id
|
282
|
+
rescue Exception => e
|
283
|
+
res = Log.format("Failed to reconnect to broker #{id} to tune heartbeat", e)
|
284
|
+
Log.error("Failed to reconnect to broker #{id} to tune heartbeat", e, :trace)
|
285
|
+
@exceptions.track("tune heartbeat", e)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
res = "Failed to tune heartbeat for brokers #{(all - ids).inspect}" unless (all - ids).empty?
|
289
|
+
rescue Exception => e
|
290
|
+
res = Log.format("Failed tuning broker connection heartbeat", e)
|
291
|
+
Log.error("Failed tuning broker connection heartbeat", e, :trace)
|
292
|
+
@exceptions.track("tune heartbeat", e)
|
293
|
+
end
|
294
|
+
res
|
295
|
+
end
|
296
|
+
|
242
297
|
# Connect to an additional broker or reconnect it if connection has failed
|
243
298
|
# Subscribe to identity queue on this broker
|
244
299
|
# Update config file if this is a new broker
|
@@ -384,6 +439,17 @@ module RightScale
|
|
384
439
|
true
|
385
440
|
end
|
386
441
|
|
442
|
+
# Defer task until next status check
|
443
|
+
#
|
444
|
+
# === Block
|
445
|
+
# Required block to be activated on next status check
|
446
|
+
#
|
447
|
+
# === Return
|
448
|
+
# true:: Always return true
|
449
|
+
def defer_task(&task)
|
450
|
+
@deferred_tasks << task
|
451
|
+
end
|
452
|
+
|
387
453
|
# Gracefully terminate execution by allowing unfinished tasks to complete
|
388
454
|
# Immediately terminate if called a second time
|
389
455
|
#
|
@@ -462,6 +528,7 @@ module RightScale
|
|
462
528
|
result = OperationResult.success("name" => @agent_name,
|
463
529
|
"identity" => @identity,
|
464
530
|
"hostname" => Socket.gethostname,
|
531
|
+
"memory" => Platform.process.resident_set_size,
|
465
532
|
"version" => AgentConfig.protocol_version,
|
466
533
|
"brokers" => @broker.stats(reset),
|
467
534
|
"agent stats" => agent_stats(reset),
|
@@ -674,12 +741,22 @@ module RightScale
|
|
674
741
|
true
|
675
742
|
end
|
676
743
|
|
677
|
-
# Check status of agent by gathering current operation statistics and publishing them
|
678
|
-
#
|
744
|
+
# Check status of agent by gathering current operation statistics and publishing them,
|
745
|
+
# executing any deferred tasks, and finishing any queue setup
|
679
746
|
#
|
680
747
|
# === Return
|
681
748
|
# true:: Always return true
|
682
749
|
def check_status
|
750
|
+
@deferred_tasks.reject! do |t|
|
751
|
+
begin
|
752
|
+
t.call
|
753
|
+
rescue Exception => e
|
754
|
+
Log.error("Failed to perform deferred task", e)
|
755
|
+
@exceptions.track("check status", e)
|
756
|
+
end
|
757
|
+
true
|
758
|
+
end
|
759
|
+
|
683
760
|
begin
|
684
761
|
finish_setup
|
685
762
|
rescue Exception => e
|
@@ -63,7 +63,7 @@ module RightScale
|
|
63
63
|
module AgentConfig
|
64
64
|
|
65
65
|
# Current agent protocol version
|
66
|
-
PROTOCOL_VERSION =
|
66
|
+
PROTOCOL_VERSION = 18
|
67
67
|
|
68
68
|
# Current agent protocol version
|
69
69
|
#
|
@@ -344,6 +344,22 @@ module RightScale
|
|
344
344
|
options || {}
|
345
345
|
end
|
346
346
|
|
347
|
+
# Agents that are currently running
|
348
|
+
#
|
349
|
+
# === Parameters
|
350
|
+
# (Regexp):: Pattern that agent name must match to be included
|
351
|
+
#
|
352
|
+
# === Return
|
353
|
+
# (Array):: Name of running agents
|
354
|
+
def self.running_agents(pattern = //)
|
355
|
+
AgentConfig.cfg_agents.select do |agent_name|
|
356
|
+
agent_name =~ pattern &&
|
357
|
+
(pid_file = AgentConfig.pid_file(agent_name)) &&
|
358
|
+
(pid = pid_file.read_pid[:pid]) &&
|
359
|
+
(Process.getpgid(pid) rescue -1) != -1
|
360
|
+
end.sort
|
361
|
+
end
|
362
|
+
|
347
363
|
protected
|
348
364
|
|
349
365
|
# Convert value to array if not an array, unless nil
|
@@ -40,7 +40,7 @@ module RightScale
|
|
40
40
|
# === Return
|
41
41
|
# true:: Always return true
|
42
42
|
def tags
|
43
|
-
do_query do |result|
|
43
|
+
do_query(nil, @agent.identity) do |result|
|
44
44
|
if result.kind_of?(Hash)
|
45
45
|
yield(result.size == 1 ? result.values.first['tags'] : [])
|
46
46
|
else
|
@@ -178,7 +178,7 @@ module RightScale
|
|
178
178
|
# true:: Always return true
|
179
179
|
def do_query(tags = nil, agent_ids = nil, raw = false)
|
180
180
|
agent_check
|
181
|
-
payload = {:
|
181
|
+
payload = {:agent_identity => @agent.identity}
|
182
182
|
payload[:tags] = ensure_flat_array_value(tags) unless tags.nil? || tags.empty?
|
183
183
|
payload[:agent_ids] = ensure_flat_array_value(agent_ids) unless agent_ids.nil? || agent_ids.empty?
|
184
184
|
request = RightScale::IdempotentRequest.new("/mapper/query_tags", payload)
|
@@ -37,8 +37,8 @@ module RightScale
|
|
37
37
|
:failed # Failed to connect due to internal failure or AMQP failure to connect
|
38
38
|
]
|
39
39
|
|
40
|
-
# (
|
41
|
-
attr_reader :
|
40
|
+
# (AMQP::Channel) Channel of AMQP connection used by this client
|
41
|
+
attr_reader :channel
|
42
42
|
|
43
43
|
# (String) Broker identity
|
44
44
|
attr_reader :identity
|
@@ -99,6 +99,8 @@ module RightScale
|
|
99
99
|
# :vhost(String):: Virtual host path name
|
100
100
|
# :insist(Boolean):: Whether to suppress redirection of connection
|
101
101
|
# :reconnect_interval(Integer):: Number of seconds between reconnect attempts
|
102
|
+
# :heartbeat(Integer):: Number of seconds between AMQP connection heartbeats used to keep
|
103
|
+
# connection alive, e.g., when AMQP broker is behind a firewall
|
102
104
|
# :prefetch(Integer):: Maximum number of messages the AMQP broker is to prefetch for the agent
|
103
105
|
# before it receives an ack. Value 1 ensures that only last unacknowledged gets redelivered
|
104
106
|
# if the agent crashes. Value 0 means unlimited prefetch.
|
@@ -217,13 +219,13 @@ module RightScale
|
|
217
219
|
|
218
220
|
begin
|
219
221
|
Log.info("[setup] Subscribing queue #{queue[:name]}#{to_exchange} on broker #{@alias}")
|
220
|
-
q = @
|
222
|
+
q = @channel.queue(queue[:name], queue_options)
|
221
223
|
@queues << q
|
222
224
|
if exchange
|
223
|
-
x = @
|
225
|
+
x = @channel.__send__(exchange[:type], exchange[:name], exchange_options)
|
224
226
|
binding = q.bind(x, options[:key] ? {:key => options[:key]} : {})
|
225
227
|
if exchange2 = options[:exchange2]
|
226
|
-
q.bind(@
|
228
|
+
q.bind(@channel.__send__(exchange2[:type], exchange2[:name], exchange2[:options] || {}))
|
227
229
|
end
|
228
230
|
q = binding
|
229
231
|
end
|
@@ -319,8 +321,8 @@ module RightScale
|
|
319
321
|
return false unless usable?
|
320
322
|
begin
|
321
323
|
Log.info("[setup] Declaring #{name} #{type.to_s} on broker #{@alias}")
|
322
|
-
|
323
|
-
@
|
324
|
+
delete_amqp_resources(:queue, name)
|
325
|
+
@channel.__send__(type, name, options)
|
324
326
|
true
|
325
327
|
rescue Exception => e
|
326
328
|
Log.error("Failed declaring #{type.to_s} #{name} on broker #{@alias}", e, :trace)
|
@@ -361,8 +363,8 @@ module RightScale
|
|
361
363
|
end
|
362
364
|
Log.debug("... publish options #{options.inspect}, exchange #{exchange[:name]}, " +
|
363
365
|
"type #{exchange[:type]}, options #{exchange[:options].inspect}")
|
364
|
-
|
365
|
-
@
|
366
|
+
delete_amqp_resources(exchange[:type], exchange[:name]) if exchange_options[:declare]
|
367
|
+
@channel.__send__(exchange[:type], exchange[:name], exchange_options).publish(message, options)
|
366
368
|
true
|
367
369
|
rescue Exception => e
|
368
370
|
Log.error("Failed publishing to exchange #{exchange.inspect} on broker #{@alias}", e, :trace)
|
@@ -390,7 +392,7 @@ module RightScale
|
|
390
392
|
# === Return
|
391
393
|
# true:: Always return true
|
392
394
|
def return_message
|
393
|
-
@
|
395
|
+
@channel.return_message do |info, message|
|
394
396
|
begin
|
395
397
|
to = if info.exchange && !info.exchange.empty? then info.exchange else info.routing_key end
|
396
398
|
reason = info.reply_text
|
@@ -418,14 +420,14 @@ module RightScale
|
|
418
420
|
begin
|
419
421
|
@queues.reject! do |q|
|
420
422
|
if q.name == name
|
421
|
-
@
|
423
|
+
@channel.queue(name, options.merge(:no_declare => true)).delete
|
422
424
|
deleted = true
|
423
425
|
end
|
424
426
|
end
|
425
427
|
unless deleted
|
426
428
|
# Allowing declare to happen since queue may not exist and do not want NOT_FOUND
|
427
429
|
# failure to cause AMQP channel to close
|
428
|
-
@
|
430
|
+
@channel.queue(name, options).delete
|
429
431
|
deleted = true
|
430
432
|
end
|
431
433
|
rescue Exception => e
|
@@ -436,6 +438,19 @@ module RightScale
|
|
436
438
|
deleted
|
437
439
|
end
|
438
440
|
|
441
|
+
# Delete resources from local AMQP cache
|
442
|
+
#
|
443
|
+
# === Parameters
|
444
|
+
# type(Symbol):: Type of AMQP object
|
445
|
+
# name(String):: Name of object
|
446
|
+
#
|
447
|
+
# === Return
|
448
|
+
# true:: Always return true
|
449
|
+
def delete_amqp_resources(type, name)
|
450
|
+
@channel.__send__(type == :queue ? :queues : :exchanges).delete(name)
|
451
|
+
true
|
452
|
+
end
|
453
|
+
|
439
454
|
# Close broker connection
|
440
455
|
#
|
441
456
|
# === Parameters
|
@@ -520,7 +535,7 @@ module RightScale
|
|
520
535
|
# Makes client callback with :connected or :disconnected status if boundary crossed
|
521
536
|
#
|
522
537
|
# === Parameters
|
523
|
-
# status(Symbol):: Status of connection (:connected, :
|
538
|
+
# status(Symbol):: Status of connection (:connected, :disconnected, :stopping, :failed, :closed)
|
524
539
|
#
|
525
540
|
# === Return
|
526
541
|
# true:: Always return true
|
@@ -528,11 +543,6 @@ module RightScale
|
|
528
543
|
# Do not let closed connection regress to failed
|
529
544
|
return true if status == :failed && @status == :closed
|
530
545
|
|
531
|
-
# Wait until connection is ready (i.e. handshake with broker is completed) before
|
532
|
-
# changing our status to connected
|
533
|
-
return true if status == :connected
|
534
|
-
status = :connected if status == :ready
|
535
|
-
|
536
546
|
before = @status
|
537
547
|
@status = status
|
538
548
|
|
@@ -574,11 +584,12 @@ module RightScale
|
|
574
584
|
:host => address[:host],
|
575
585
|
:port => address[:port],
|
576
586
|
:insist => @options[:insist] || false,
|
587
|
+
:heartbeat => @options[:heartbeat],
|
577
588
|
:reconnect_delay => lambda { rand(reconnect_interval) },
|
578
589
|
:reconnect_interval => reconnect_interval)
|
579
|
-
@
|
580
|
-
@
|
581
|
-
@
|
590
|
+
@channel = AMQP::Channel.new(@connection)
|
591
|
+
@channel.__send__(:connection).connection_status { |status| update_status(status) }
|
592
|
+
@channel.prefetch(@options[:prefetch]) if @options[:prefetch]
|
582
593
|
rescue Exception => e
|
583
594
|
@status = :failed
|
584
595
|
@failures.update
|
@@ -653,19 +664,6 @@ module RightScale
|
|
653
664
|
true
|
654
665
|
end
|
655
666
|
|
656
|
-
# Delete object from local AMQP cache in case it is no longer consistent with broker
|
657
|
-
#
|
658
|
-
# === Parameters
|
659
|
-
# type(Symbol):: Type of AMQP object
|
660
|
-
# name(String):: Name of object
|
661
|
-
#
|
662
|
-
# === Return
|
663
|
-
# true:: Always return true
|
664
|
-
def delete_from_cache(type, name)
|
665
|
-
@mq.__send__(type == :queue ? :queues : :exchanges).delete(name)
|
666
|
-
true
|
667
|
-
end
|
668
|
-
|
669
667
|
# Execute packet receive callback, make it a separate method to ease instrumentation
|
670
668
|
#
|
671
669
|
# === Parameters
|