right_agent 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/lib/right_agent.rb +1 -0
  3. data/lib/right_agent/actor.rb +0 -28
  4. data/lib/right_agent/actors/agent_manager.rb +20 -18
  5. data/lib/right_agent/agent.rb +69 -87
  6. data/lib/right_agent/agent_tag_manager.rb +1 -1
  7. data/lib/right_agent/clients/api_client.rb +0 -1
  8. data/lib/right_agent/clients/auth_client.rb +2 -6
  9. data/lib/right_agent/clients/balanced_http_client.rb +2 -2
  10. data/lib/right_agent/clients/base_retry_client.rb +12 -19
  11. data/lib/right_agent/clients/right_http_client.rb +1 -5
  12. data/lib/right_agent/clients/router_client.rb +8 -15
  13. data/lib/right_agent/command/command_parser.rb +3 -3
  14. data/lib/right_agent/command/command_runner.rb +1 -1
  15. data/lib/right_agent/connectivity_checker.rb +7 -11
  16. data/lib/right_agent/dispatcher.rb +7 -42
  17. data/lib/right_agent/enrollment_result.rb +2 -2
  18. data/lib/right_agent/error_tracker.rb +202 -0
  19. data/lib/right_agent/log.rb +0 -2
  20. data/lib/right_agent/packets.rb +1 -1
  21. data/lib/right_agent/pending_requests.rb +10 -4
  22. data/lib/right_agent/pid_file.rb +3 -3
  23. data/lib/right_agent/protocol_version_mixin.rb +3 -3
  24. data/lib/right_agent/scripts/agent_deployer.rb +13 -1
  25. data/lib/right_agent/sender.rb +14 -30
  26. data/lib/right_agent/serialize/secure_serializer.rb +4 -4
  27. data/right_agent.gemspec +2 -2
  28. data/spec/agent_spec.rb +5 -5
  29. data/spec/clients/auth_client_spec.rb +1 -1
  30. data/spec/clients/balanced_http_client_spec.rb +4 -2
  31. data/spec/clients/base_retry_client_spec.rb +5 -6
  32. data/spec/clients/router_client_spec.rb +1 -4
  33. data/spec/dispatcher_spec.rb +6 -55
  34. data/spec/error_tracker_spec.rb +293 -0
  35. data/spec/pending_requests_spec.rb +2 -2
  36. data/spec/sender_spec.rb +3 -3
  37. data/spec/spec_helper.rb +4 -2
  38. metadata +33 -66
@@ -185,7 +185,7 @@ module RightScale
185
185
  request = RightScale::RetryableRequest.new("/router/query_tags", payload, request_options)
186
186
  request.callback { |result| yield raw ? request.raw_response : result }
187
187
  request.errback do |message|
188
- Log.error("Failed to query tags (#{message})")
188
+ ErrorTracker.log(self, "Failed to query tags (#{message})")
189
189
  yield((raw ? request.raw_response : nil) || message)
190
190
  end
191
191
  request.run
@@ -83,7 +83,6 @@ module RightScale
83
83
  # @option options [Array] :retry_intervals between successive retries; defaults to DEFAULT_RETRY_INTERVALS
84
84
  # @option options [Boolean] :retry_enabled for requests that fail to connect or that return a retry result
85
85
  # @option options [Numeric] :reconnect_interval for reconnect attempts after lose connectivity
86
- # @option options [Proc] :exception_callback for unexpected exceptions
87
86
  #
88
87
  # @raise [ArgumentError] auth client does not support this client type
89
88
  def initialize(auth_client, options)
@@ -175,7 +175,6 @@ module RightScale
175
175
  #
176
176
  # @return [Hash] current statistics
177
177
  # [Hash, NilClass] "state" Activity stats or nil if none
178
- # [Hash, NilClass] "exceptions" Exceptions stats or nil if none
179
178
  def stats(reset = false)
180
179
  stats = {}
181
180
  @stats.each { |k, v| stats[k] = v.all }
@@ -189,9 +188,7 @@ module RightScale
189
188
  #
190
189
  # @return [TrueClass] always true
191
190
  def reset_stats
192
- @stats = {
193
- "state" => RightSupport::Stats::Activity.new,
194
- "exceptions" => RightSupport::Stats::Exceptions.new(agent = nil, @exception_callback)}
191
+ @stats = {"state" => RightSupport::Stats::Activity.new}
195
192
  true
196
193
  end
197
194
 
@@ -246,8 +243,7 @@ module RightScale
246
243
  begin
247
244
  callback.call(:auth, @state)
248
245
  rescue StandardError => e
249
- Log.error("Failed status callback", e)
250
- @stats["exceptions"].track("status", e)
246
+ ErrorTracker.log(self, "Failed status callback", e, nil, :caller)
251
247
  end
252
248
  end
253
249
  end
@@ -178,7 +178,7 @@ module RightScale
178
178
  e2 = HttpExceptions.convert(e)
179
179
  log_failure(used[:host], path, params, filter, request_uuid, started_at, e2)
180
180
  raise e2
181
- rescue Exception => e
181
+ rescue StandardError => e
182
182
  log_failure(used[:host], path, params, filter, request_uuid, started_at, e)
183
183
  raise
184
184
  end
@@ -345,7 +345,7 @@ module RightScale
345
345
  def log_failure(host, path, params, filter, request_uuid, started_at, exception)
346
346
  code = exception.respond_to?(:http_code) ? exception.http_code : "nil"
347
347
  duration = "%.0fms" % ((Time.now - started_at) * 1000)
348
- Log.error("Failed <#{request_uuid}> in #{duration} | #{code} " + log_text(path, params, filter, host, exception))
348
+ ErrorTracker.log(self, "Failed <#{request_uuid}> in #{duration} | #{code} " + log_text(path, params, filter, host, exception))
349
349
  true
350
350
  end
351
351
 
@@ -77,7 +77,6 @@ module RightScale
77
77
  # EM::HttpRequest and fibers instead of RestClient; requests remain synchronous
78
78
  # @option options [Array] :filter_params symbols or strings for names of request parameters
79
79
  # whose values are to be hidden when logging; can be augmented on individual requests
80
- # @option options [Proc] :exception_callback for unexpected exceptions
81
80
  #
82
81
  # @return [Boolean] whether currently connected
83
82
  #
@@ -161,7 +160,6 @@ module RightScale
161
160
  # [Hash, NilClass] "request sent" Activity stats or nil if none
162
161
  # [Float, NilClass] "response time" average number of seconds to respond to a request or nil if none
163
162
  # [Hash, NilClass] "state" Activity stats or nil if none
164
- # [Hash, NilClass] "exceptions" Exceptions stats or nil if none
165
163
  def stats(reset = false)
166
164
  stats = {}
167
165
  @stats.each { |k, v| stats[k] = v.all }
@@ -180,8 +178,7 @@ module RightScale
180
178
  "reconnects" => RightSupport::Stats::Activity.new,
181
179
  "request failures" => RightSupport::Stats::Activity.new,
182
180
  "requests sent" => RightSupport::Stats::Activity.new,
183
- "state" => RightSupport::Stats::Activity.new,
184
- "exceptions" => RightSupport::Stats::Exceptions.new(agent = nil, @options[:exception_callback]) }
181
+ "state" => RightSupport::Stats::Activity.new }
185
182
  true
186
183
  end
187
184
 
@@ -212,8 +209,7 @@ module RightScale
212
209
  begin
213
210
  callback.call(@type, @state)
214
211
  rescue StandardError => e
215
- Log.error("Failed status callback", e)
216
- @stats["exceptions"].track("status", e)
212
+ ErrorTracker.log(self, "Failed status callback", e, nil, :caller)
217
213
  end
218
214
  end
219
215
  reconnect if @state == :disconnected
@@ -248,9 +244,8 @@ module RightScale
248
244
  def close_http_client(reason)
249
245
  @http_client.close(reason) if @http_client
250
246
  true
251
- rescue Exception => e
252
- Log.error("Failed closing connection", e, :trace)
253
- @stats["exceptions"].track("status", e)
247
+ rescue StandardError => e
248
+ ErrorTracker.log(self, "Failed closing connection", e)
254
249
  false
255
250
  end
256
251
 
@@ -271,11 +266,10 @@ module RightScale
271
266
  @http_client.check_health
272
267
  self.state = :connected
273
268
  rescue BalancedHttpClient::NotResponding => e
274
- Log.error("Failed #{@options[:server_name]} health check", e.nested_exception)
269
+ ErrorTracker.log(self, "Failed #{@options[:server_name]} health check", e.nested_exception)
275
270
  self.state = :disconnected
276
- rescue Exception => e
277
- Log.error("Failed #{@options[:server_name]} health check", e)
278
- @stats["exceptions"].track("check health", e)
271
+ rescue StandardError => e
272
+ ErrorTracker.log(self, "Failed #{@options[:server_name]} health check", e, nil, :caller)
279
273
  self.state = :disconnected
280
274
  end
281
275
  end
@@ -298,9 +292,8 @@ module RightScale
298
292
  @reconnect_timer = @reconnecting = nil
299
293
  end
300
294
  rescue Exception => e
301
- Log.error("Failed #{@options[:server_name]} reconnect", e)
295
+ ErrorTracker.log(self, "Failed #{@options[:server_name]} reconnect", e, nil, :caller)
302
296
  @stats["reconnects"].update("failure")
303
- @stats["exceptions"].track("reconnect", e)
304
297
  self.state = :disconnected
305
298
  end
306
299
  @reconnect_timer.interval = @options[:reconnect_interval] if @reconnect_timer
@@ -472,8 +465,8 @@ module RightScale
472
465
  @stats["request failures"].update("#{type} - retry")
473
466
  raise Exceptions::RetryableError.new(retry_result.http_body, retry_result)
474
467
  else
475
- Log.error("Retrying #{type} request <#{request_uuid}> in #{interval} seconds " +
476
- "in response to retryable error (#{retry_result.http_body})")
468
+ ErrorTracker.log(self, "Retrying #{type} request <#{request_uuid}> in #{interval} seconds " +
469
+ "in response to retryable error (#{retry_result.http_body})")
477
470
  wait(interval)
478
471
  end
479
472
  # Change request_uuid so that retried request not rejected as duplicate
@@ -505,8 +498,8 @@ module RightScale
505
498
  self.state = :disconnected
506
499
  raise Exceptions::ConnectivityFailure.new(not_responding.message + " after #{attempts} attempts")
507
500
  else
508
- Log.error("Retrying #{type} request <#{request_uuid}> in #{interval} seconds " +
509
- "in response to routing failure (#{BalancedHttpClient.exception_text(not_responding)})")
501
+ ErrorTracker.log(self, "Retrying #{type} request <#{request_uuid}> in #{interval} seconds " +
502
+ "in response to routing failure (#{BalancedHttpClient.exception_text(not_responding)})")
510
503
  wait(interval)
511
504
  end
512
505
  true
@@ -51,10 +51,6 @@ module RightScale
51
51
  # @option options [Boolean] :long_polling_only never attempt to create a WebSocket, always long-polling instead
52
52
  # @option options [Array] :filter_params symbols or strings for names of request parameters
53
53
  # whose values are to be hidden when logging
54
- # @option options [Proc] :exception_callback for unexpected exceptions with following parameters:
55
- # [Exception] exception raised
56
- # [Packet, NilClass] packet being processed
57
- # [Agent, NilClass] agent in which exception occurred
58
54
  #
59
55
  # @return [TrueClass] always true
60
56
  #
@@ -275,7 +271,7 @@ module RightScale
275
271
  begin
276
272
  callback.call(type, state)
277
273
  rescue RuntimeError => e
278
- Log.error("Failed status callback", e)
274
+ ErrorTracker.log(self, "Failed status callback", e, nil, :caller)
279
275
  end
280
276
  end
281
277
  @status
@@ -88,7 +88,6 @@ module RightScale
88
88
  # @option options [Numeric] :reconnect_interval for reconnect attempts after lose connectivity
89
89
  # @option options [Boolean] :non_blocking i/o is to be used for HTTP requests by applying
90
90
  # EM::HttpRequest and fibers instead of RestClient; requests remain synchronous
91
- # @option options [Proc] :exception_callback for unexpected exceptions
92
91
  #
93
92
  # @raise [ArgumentError] auth client does not support this client type
94
93
  def initialize(auth_client, options)
@@ -262,7 +261,6 @@ module RightScale
262
261
  # [Hash, NilClass] "request failures" Activity stats or nil if none
263
262
  # [Hash, NilClass] "request sent" Activity stats or nil if none
264
263
  # [Float, NilClass] "response time" average number of seconds to respond to a request or nil if none
265
- # [Hash, NilClass] "exceptions" Exceptions stats or nil if none
266
264
  def stats(reset = false)
267
265
  events = @stats["events"].all
268
266
  stats = super(reset)
@@ -337,11 +335,10 @@ module RightScale
337
335
  end
338
336
  @listen_failures = 0
339
337
  rescue Exception => e
340
- Log.error("Failed to listen", e, :trace)
341
- @stats["exceptions"].track("listen", e)
338
+ ErrorTracker.log(self, "Failed to listen", e)
342
339
  @listen_failures += 1
343
340
  if @listen_failures > MAX_LISTEN_FAILURES
344
- Log.error("Exceeded maximum repeated listen failures (#{MAX_LISTEN_FAILURES}), stopping listening")
341
+ ErrorTracker.log(self, "Exceeded maximum repeated listen failures (#{MAX_LISTEN_FAILURES}), stopping listening")
345
342
  @listen_state = :cancel
346
343
  self.state = :failed
347
344
  return false
@@ -440,8 +437,7 @@ module RightScale
440
437
  connect(routing_keys, &handler)
441
438
  update_listen_state(:check, 1)
442
439
  rescue Exception => e
443
- Log.error("Failed creating WebSocket", e)
444
- @stats["exceptions"].track("websocket", e)
440
+ ErrorTracker.log(self, "Failed creating WebSocket", e, nil, :caller)
445
441
  backoff_connect_interval
446
442
  update_listen_state(:long_poll)
447
443
  end
@@ -477,7 +473,7 @@ module RightScale
477
473
  @websocket = Faye::WebSocket::Client.new(url.to_s, protocols = nil, options)
478
474
 
479
475
  @websocket.onerror = lambda do |event|
480
- Log.error("WebSocket error (#{event.data})") if event.data
476
+ ErrorTracker.log(self, "WebSocket error (#{event.data})") if event.data
481
477
  end
482
478
 
483
479
  @websocket.onclose = lambda do |event|
@@ -488,8 +484,7 @@ module RightScale
488
484
  msg << ((event.reason.nil? || event.reason.empty?) ? ")" : ": #{event.reason})")
489
485
  Log.info(msg)
490
486
  rescue Exception => e
491
- Log.error("Failed closing WebSocket", e, :trace)
492
- @stats["exceptions"].track("event", e)
487
+ ErrorTracker.log(self, "Failed closing WebSocket", e)
493
488
  end
494
489
  @websocket = nil
495
490
  end
@@ -508,8 +503,7 @@ module RightScale
508
503
  handler.call(event)
509
504
  @communicated_callbacks.each { |callback| callback.call } if @communicated_callbacks
510
505
  rescue Exception => e
511
- Log.error("Failed handling WebSocket event", e, :trace)
512
- @stats["exceptions"].track("event", e)
506
+ ErrorTracker.log(self, "Failed handling WebSocket event", e)
513
507
  end
514
508
  end
515
509
 
@@ -596,6 +590,7 @@ module RightScale
596
590
  end
597
591
 
598
592
  # Process result from long-polling attempt
593
+ # Not necessary to log failure since should already have been done by underlying HTTP client
599
594
  #
600
595
  # @param [Array, NilClass] result from long-polling attempt
601
596
  #
@@ -603,12 +598,10 @@ module RightScale
603
598
  def process_long_poll(result)
604
599
  case result
605
600
  when Exceptions::Unauthorized, Exceptions::ConnectivityFailure, Exceptions::RetryableError, Exceptions::InternalServerError
606
- Log.error("Failed long-polling", result, :no_trace)
607
601
  update_listen_state(:choose, backoff_reconnect_interval)
608
602
  result = nil
609
603
  when Exception
610
- Log.error("Failed long-polling", result, :trace)
611
- @stats["exceptions"].track("long-polling", result)
604
+ ErrorTracker.track(self, result)
612
605
  update_listen_state(:choose, backoff_reconnect_interval)
613
606
  result = nil
614
607
  else
@@ -51,12 +51,12 @@ module RightScale
51
51
  def parse_chunk(chunk)
52
52
  @buildup << chunk
53
53
  chunks = @buildup.split(CommandSerializer::SEPARATOR, -1)
54
- if do_call = chunks.size > 1
54
+ if (do_call = chunks.size > 1)
55
55
  commands = []
56
56
  (0..chunks.size - 2).each do |i|
57
57
  begin
58
58
  commands << CommandSerializer.load(chunks[i])
59
- rescue Exception => e
59
+ rescue StandardError => e
60
60
  # log any exceptions caused by serializing individual chunks instead
61
61
  # of halting EM. each command is discrete so we need to keep trying
62
62
  # so long as there are more commands to process (although subsequent
@@ -77,7 +77,7 @@ module RightScale
77
77
  @buildup = chunks.last
78
78
  end
79
79
  do_call
80
- rescue Exception => e
80
+ rescue StandardError => e
81
81
  # log any other exceptions instead of halting EM.
82
82
  Log.error("Failed parsing command chunk", e, :trace)
83
83
  end
@@ -79,7 +79,7 @@ module RightScale
79
79
  Log.error("Invalid cookie used by command protocol client (#{cmd_cookie})")
80
80
  end
81
81
  rescue Exception => e
82
- Log.warning("Command failed (#{e.message}) at\n#{e.backtrace.join("\n")}")
82
+ Log.error("Command failed", e, :trace)
83
83
  end
84
84
  end
85
85
 
@@ -38,13 +38,12 @@ module RightScale
38
38
  # Timer while waiting for RightNet router ping response
39
39
  attr_accessor :ping_timer
40
40
 
41
- def initialize(sender, check_interval, ping_stats, exception_stats)
41
+ def initialize(sender, check_interval, ping_stats)
42
42
  @sender = sender
43
43
  @check_interval = check_interval
44
44
  @ping_timeouts = {}
45
45
  @ping_timer = nil
46
46
  @ping_stats = ping_stats
47
- @exception_stats = exception_stats
48
47
  @last_received = Time.now
49
48
  @message_received_callbacks = []
50
49
  restart_inactivity_timer if @check_interval > 0
@@ -98,17 +97,16 @@ module RightScale
98
97
  @ping_timer = nil
99
98
  @ping_timeouts[@ping_id] = (@ping_timeouts[@ping_id] || 0) + 1
100
99
  if @ping_timeouts[@ping_id] >= max_ping_timeouts
101
- Log.error("Mapper ping via broker #{@ping_id} timed out after #{PING_TIMEOUT} seconds and now " +
102
- "reached maximum of #{max_ping_timeouts} timeout#{max_ping_timeouts > 1 ? 's' : ''}, " +
103
- "attempting to reconnect")
100
+ ErrorTracker.log(self, "Mapper ping via broker #{@ping_id} timed out after #{PING_TIMEOUT} seconds and now " +
101
+ "reached maximum of #{max_ping_timeouts} timeout#{max_ping_timeouts > 1 ? 's' : ''}, " +
102
+ "attempting to reconnect")
104
103
  host, port, index, priority = @sender.client.identity_parts(@ping_id)
105
104
  @sender.agent.connect(host, port, index, priority, force = true)
106
105
  else
107
106
  Log.warning("Mapper ping via broker #{@ping_id} timed out after #{PING_TIMEOUT} seconds")
108
107
  end
109
108
  rescue Exception => e
110
- Log.error("Failed to reconnect to broker #{@ping_id}", e, :trace)
111
- @exception_stats.track("ping timeout", e)
109
+ ErrorTracker.log(self, "Failed to reconnect to broker #{@ping_id}", e)
112
110
  end
113
111
  else
114
112
  @ping_timer = nil
@@ -125,8 +123,7 @@ module RightScale
125
123
  @ping_id = nil
126
124
  end
127
125
  rescue Exception => e
128
- Log.error("Failed to cancel router ping", e, :trace)
129
- @exception_stats.track("cancel ping", e)
126
+ ErrorTracker.log(self, "Failed to cancel router ping", e)
130
127
  end
131
128
  end
132
129
  request = Request.new("/router/ping", nil, {:from => @sender.identity, :token => AgentIdentity.generate})
@@ -167,8 +164,7 @@ module RightScale
167
164
  begin
168
165
  check(id = nil, max_ping_timeouts = 1)
169
166
  rescue Exception => e
170
- Log.error("Failed connectivity check", e, :trace)
171
- @exception_stats.track("check connectivity", e)
167
+ ErrorTracker.log(self, "Failed connectivity check", e)
172
168
  end
173
169
  end
174
170
  true
@@ -27,8 +27,8 @@ module RightScale
27
27
 
28
28
  include ProtocolVersionMixin
29
29
 
30
- class InvalidRequestType < Exception; end
31
- class DuplicateRequest < Exception; end
30
+ class InvalidRequestType < RuntimeError; end
31
+ class DuplicateRequest < RuntimeError; end
32
32
 
33
33
  # (ActorRegistry) Registry for actors
34
34
  attr_reader :registry
@@ -88,7 +88,7 @@ module RightScale
88
88
  actor, method, idempotent = route(request)
89
89
  received_at = @request_stats.update(method, (token if request.is_a?(Request)))
90
90
  if (dup = duplicate?(request, method, idempotent))
91
- raise DuplicateRequest.new(dup)
91
+ raise DuplicateRequest, dup
92
92
  end
93
93
  unless (result = expired?(request, method))
94
94
  result = perform(request, actor, method, idempotent)
@@ -110,9 +110,6 @@ module RightScale
110
110
  # or nil if empty
111
111
  # "dispatch failures"(Hash|nil):: Dispatch failure activity stats with keys "total", "percent", "last", and "rate"
112
112
  # with percentage breakdown per failure type, or nil if none
113
- # "exceptions"(Hash|nil):: Exceptions raised per category, or nil if none
114
- # "total"(Integer):: Total for category
115
- # "recent"(Array):: Most recent as a hash of "count", "type", "message", "when", and "where"
116
113
  # "rejects"(Hash|nil):: Request reject activity stats with keys "total", "percent", "last", and "rate"
117
114
  # with percentage breakdown per reason ("duplicate (<method>)", "retry duplicate (<method>)", or
118
115
  # "stale (<method>)"), or nil if none
@@ -123,7 +120,6 @@ module RightScale
123
120
  stats = {
124
121
  "dispatched cache" => (@dispatched_cache.stats if @dispatched_cache),
125
122
  "dispatch failures" => @dispatch_failure_stats.all,
126
- "exceptions" => @exception_stats.stats,
127
123
  "rejects" => @reject_stats.all,
128
124
  "requests" => @request_stats.all,
129
125
  "response time" => @request_stats.avg_duration
@@ -142,7 +138,6 @@ module RightScale
142
138
  @reject_stats = RightSupport::Stats::Activity.new
143
139
  @request_stats = RightSupport::Stats::Activity.new
144
140
  @dispatch_failure_stats = RightSupport::Stats::Activity.new
145
- @exception_stats = RightSupport::Stats::Exceptions.new(@agent, @agent.exception_callback)
146
141
  true
147
142
  end
148
143
 
@@ -209,7 +204,7 @@ module RightScale
209
204
  method = method.to_sym
210
205
  actor = @registry.actor_for(prefix)
211
206
  if actor.nil? || !actor.respond_to?(method)
212
- raise InvalidRequestType.new("Unknown actor or method for dispatching request <#{request.token}> of type #{request.type}")
207
+ raise InvalidRequestType, "Unknown actor or method for dispatching request <#{request.token}> of type #{request.type}"
213
208
  end
214
209
  [actor, method, actor.class.idempotent?(method)]
215
210
  end
@@ -231,40 +226,10 @@ module RightScale
231
226
  else
232
227
  actor.send(method, request.payload, request)
233
228
  end
234
- rescue Exception => e
229
+ rescue StandardError => e
230
+ ErrorTracker.log(self, "Failed dispatching #{request.trace}", e, request)
235
231
  @dispatch_failure_stats.update("#{request.type}->#{e.class.name}")
236
- OperationResult.error(handle_exception(actor, method, request, e))
237
- end
238
-
239
- # Handle exception by logging it, calling the actors exception callback method,
240
- # and gathering exception statistics
241
- #
242
- # === Parameters
243
- # actor(Actor):: Actor that failed to process request
244
- # method(Symbol):: Name of actor method being dispatched to
245
- # request(Packet):: Packet that dispatcher is acting upon
246
- # exception(Exception):: Exception that was raised
247
- #
248
- # === Return
249
- # (String):: Error description for this exception
250
- def handle_exception(actor, method, request, exception)
251
- error = "Could not handle #{request.type} request"
252
- Log.error(error, exception, :trace)
253
- begin
254
- if actor && actor.class.exception_callback
255
- case actor.class.exception_callback
256
- when Symbol, String
257
- actor.send(actor.class.exception_callback, method, request, exception)
258
- when Proc
259
- actor.instance_exec(method, request, exception, &actor.class.exception_callback)
260
- end
261
- end
262
- @exception_stats.track(request.type, exception)
263
- rescue Exception => e
264
- Log.error("Failed handling error for #{request.type}", e, :trace)
265
- @exception_stats.track(request.type, e) rescue nil
266
- end
267
- Log.format(error, exception)
232
+ OperationResult.error("Could not handle #{request.type} request", e)
268
233
  end
269
234
 
270
235
  end # Dispatcher