right_support 2.5.4 → 2.5.5

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.
@@ -99,7 +99,7 @@ end
99
99
  module RightSupport::DB
100
100
  # Exception that indicates database configuration info is missing.
101
101
  class MissingConfiguration < Exception; end
102
-
102
+ class UnsupportedRubyVersion < Exception; end
103
103
  # Base class for a column family in a keyspace
104
104
  # Used to access data persisted in Cassandra
105
105
  # Provides wrappers for Cassandra client methods
@@ -123,6 +123,11 @@ module RightSupport::DB
123
123
 
124
124
  @@connections = {}
125
125
 
126
+ # Depricate usage of CassandraModel under Ruby < 1.9
127
+ def inherited(base)
128
+ raise UnsupportedRubyVersion, "Support only Ruby >= 1.9" unless RUBY_VERSION >= "1.9"
129
+ end
130
+
126
131
  def config
127
132
  @@config
128
133
  end
@@ -270,7 +275,7 @@ module RightSupport::DB
270
275
  columns.merge!(chunk)
271
276
  if chunk.size == opt[:count]
272
277
  # Assume there are more chunks, use last key as start of next get
273
- opt[:start] = chunk.keys.sort.last
278
+ opt[:start] = chunk.keys.last
274
279
  else
275
280
  # This must be the last chunk
276
281
  break
@@ -409,7 +414,7 @@ module RightSupport::DB
409
414
  end
410
415
  if chunk.size == count
411
416
  # Assume there are more chunks, use last key as start of next get
412
- start = chunk.keys.sort.last
417
+ start = chunk.keys.last
413
418
  else
414
419
  # This must be the last chunk
415
420
  break
@@ -551,6 +556,7 @@ module RightSupport::DB
551
556
  config
552
557
  end
553
558
  end
559
+
554
560
  end # self
555
561
 
556
562
  attr_accessor :key, :attributes
@@ -29,7 +29,8 @@ module RightSupport::Net::LB
29
29
  # instead of putting it here.
30
30
  class EndpointsStack
31
31
  DEFAULT_YELLOW_STATES = 4
32
- DEFAULT_RESET_TIME = 300
32
+ DEFAULT_RESET_TIME = 60
33
+ INITIAL_N_LEVEL = 1
33
34
 
34
35
  def initialize(policy, endpoints, yellow_states=nil, reset_time=nil, on_health_change=nil)
35
36
  @policy = policy
@@ -38,7 +39,15 @@ module RightSupport::Net::LB
38
39
  @reset_time = reset_time || DEFAULT_RESET_TIME
39
40
  @on_health_change = on_health_change
40
41
  @min_n_level = 0
41
- endpoints.each { |ep| @endpoints[ep] = {:n_level => @min_n_level, :timestamp => 0} }
42
+ endpoints.each { |ep| @endpoints[ep] = {:n_level => INITIAL_N_LEVEL, :timestamp => 0} }
43
+ end
44
+
45
+ def inspect
46
+ "<#{self.class.name}: #{get_stats.inspect}>"
47
+ end
48
+
49
+ def to_s
50
+ inspect
42
51
  end
43
52
 
44
53
  def sweep
@@ -72,7 +81,7 @@ module RightSupport::Net::LB
72
81
 
73
82
  def state_color(n_level)
74
83
  color = 'green' if n_level == 0
75
- color = 'red' if n_level == @yellow_states
84
+ color = 'red' if n_level >= @yellow_states
76
85
  color = "yellow-#{n_level}" if n_level > 0 && n_level < @yellow_states
77
86
  color
78
87
  end
@@ -85,9 +94,13 @@ module RightSupport::Net::LB
85
94
  stats
86
95
  end
87
96
 
88
- def update!(endpoints)
89
- @endpoints.each { |k,v| endpoints.include?(k) ? endpoints.delete(k) : @endpoints.delete(k) }
90
- endpoints.each { |ep| @endpoints[ep] = {:n_level => @min_n_level, :timestamp => 0} }
97
+ # Replace the set of endpoints that this object knows about. If any
98
+ # endpoint in the new set is already being tracked, remember its
99
+ # health. For any new endpoint, set its health to INITIAL_N_LEVEL.
100
+
101
+ def update!(new_endpoints)
102
+ @endpoints.each { |k,v| new_endpoints.include?(k) ? new_endpoints.delete(k) : @endpoints.delete(k) }
103
+ new_endpoints.each { |ep| @endpoints[ep] = {:n_level => INITIAL_N_LEVEL, :timestamp => 0} }
91
104
  end
92
105
 
93
106
  # Return the logger that our surrounding policy uses
@@ -1,7 +1,21 @@
1
1
  module RightSupport::Net
2
2
  # Raised to indicate the (uncommon) error condition where a RequestBalancer rotated
3
- # through EVERY URL in a list without getting a non-nil, non-timeout response.
4
- class NoResult < Exception; end
3
+ # through EVERY URL in a list without getting a non-nil, non-timeout response.
4
+ #
5
+ # If the NoResult was due to a series of errors, then the #details attribute
6
+ # of this exception will let you access detailed information about the errors encountered
7
+ # while retrying the network request. #details is a Hash, the keys of which are endpoints,
8
+ # and the values of which are arrays of exceptions that we encountered while making
9
+ # requests to that endpoint.
10
+ class NoResult < Exception
11
+ # @return [Hash] a map of {endpoint => [exception_1, exception2, ...], ...}
12
+ attr_reader :details
13
+
14
+ def initialize(message, details={})
15
+ super(message)
16
+ @details = details
17
+ end
18
+ end
5
19
 
6
20
  # Utility class that allows network requests to be randomly distributed across
7
21
  # a set of network endpoints. Generally used for REST requests by passing an
@@ -38,7 +52,9 @@ module RightSupport::Net
38
52
  DEFAULT_FATAL_EXCEPTIONS = [
39
53
  NoMemoryError, SystemStackError, SignalException, SystemExit,
40
54
  ScriptError,
41
- #Subclasses of StandardError, which we can't mention directly
55
+ # Subclasses of StandardError. We can't include the base class directly as
56
+ # a fatal exception, because there are some retryable exceptions that derive
57
+ # from StandardError.
42
58
  ArgumentError, IndexError, LocalJumpError, NameError, RangeError,
43
59
  RegexpError, ThreadError, TypeError, ZeroDivisionError
44
60
  ]
@@ -186,22 +202,21 @@ module RightSupport::Net
186
202
  @policy.set_endpoints(@ips)
187
203
  end
188
204
 
189
- exceptions = []
205
+ exceptions = {}
190
206
  result = nil
191
207
  complete = false
192
208
  n = 0
193
209
 
194
210
  loop do
195
- if complete
196
- break
197
- else
211
+ if n > 0
198
212
  do_retry = @options[:retry] || DEFAULT_RETRY_PROC
199
213
  do_retry = do_retry.call(@ips || @endpoints, n) if do_retry.respond_to?(:call)
200
214
  break if (do_retry.is_a?(Integer) && n >= do_retry) || [nil, false].include?(do_retry)
201
215
  end
202
216
 
203
217
  endpoint, need_health_check = @policy.next
204
- raise NoResult, "No endpoints are available" unless endpoint
218
+ break unless endpoint
219
+
205
220
  n += 1
206
221
  t0 = Time.now
207
222
 
@@ -231,7 +246,8 @@ module RightSupport::Net
231
246
  raise(to_raise)
232
247
  else
233
248
  @policy.bad(endpoint, t0, Time.now)
234
- exceptions << e
249
+ exceptions[endpoint] ||= []
250
+ exceptions[endpoint] << e
235
251
  end
236
252
  end
237
253
 
@@ -239,14 +255,20 @@ module RightSupport::Net
239
255
 
240
256
  return result if complete
241
257
 
242
- exceptions = exceptions.map { |e| e.class.name }.uniq.join(', ')
243
- msg = "No available endpoints from #{(@ips || @endpoints).inspect}! Exceptions: #{exceptions}"
258
+ # Produce a summary message for the exception that gives a bit of detail
259
+ summary = []
260
+ exceptions.each_pair do |_, list|
261
+ list.each { |e| summary << e.class }
262
+ end
263
+ summary = summary.uniq.join(', ')
264
+ msg = "Request failed after #{n} tries to #{exceptions.keys.size} endpoints. Exceptions: #{summary}"
265
+
244
266
  logger.error "RequestBalancer: #{msg}"
245
- raise NoResult, msg
267
+ raise NoResult.new(msg, exceptions)
246
268
  end
247
269
 
248
270
  # Provide an interface so one can query the RequestBalancer for statistics on
249
- # it's endpoints. Merely proxies the balancing policy's get_stats method. If
271
+ # its endpoints. Merely proxies the balancing policy's get_stats method. If
250
272
  # no method exists in the balancing policy, a hash of endpoints with "n/a" is
251
273
  # returned.
252
274
  #
@@ -7,10 +7,10 @@ spec = Gem::Specification.new do |s|
7
7
  s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
8
8
 
9
9
  s.name = 'right_support'
10
- s.version = '2.5.4'
11
- s.date = '2012-10-05'
10
+ s.version = '2.5.5'
11
+ s.date = '2012-10-18'
12
12
 
13
- s.authors = ['Tony Spataro', 'Sergey Sergyenko', 'Ryan Williamson', 'Lee Kirchhoff', 'Sergey Enin']
13
+ s.authors = ['Tony Spataro', 'Sergey Sergyenko', 'Ryan Williamson', 'Lee Kirchhoff', 'Sergey Enin', 'Alexey Karpik']
14
14
  s.email = 'support@rightscale.com'
15
15
  s.homepage= 'https://github.com/rightscale/right_support'
16
16
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: right_support
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
8
  - 5
9
- - 4
10
- version: 2.5.4
9
+ - 5
10
+ version: 2.5.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tony Spataro
@@ -15,11 +15,12 @@ authors:
15
15
  - Ryan Williamson
16
16
  - Lee Kirchhoff
17
17
  - Sergey Enin
18
+ - Alexey Karpik
18
19
  autorequire:
19
20
  bindir: bin
20
21
  cert_chain: []
21
22
 
22
- date: 2012-10-05 00:00:00 -07:00
23
+ date: 2012-10-18 00:00:00 -07:00
23
24
  default_executable:
24
25
  dependencies: []
25
26