Class: RightSupport::Net::LB::EndpointsStack

Inherits:
Object
  • Object
show all
Defined in:
lib/right_support/net/lb/health_check.rb

Overview

TODO refactor this class. We store too much unstructured data about EPs; should have a simple class representing EP state, and then perhaps move what logic remains into the HealthCheck class instead of putting it here.

Constant Summary collapse

DEFAULT_YELLOW_STATES =
4
DEFAULT_RESET_TIME =
60
INITIAL_N_LEVEL =
1

Instance Method Summary collapse

Constructor Details

#initialize(policy, endpoints, yellow_states = nil, reset_time = nil, on_health_change = nil) ⇒ EndpointsStack

Returns a new instance of EndpointsStack.



35
36
37
38
39
40
41
42
43
# File 'lib/right_support/net/lb/health_check.rb', line 35

def initialize(policy, endpoints, yellow_states=nil, reset_time=nil, on_health_change=nil)
  @policy = policy
  @endpoints = Hash.new
  @yellow_states = yellow_states || DEFAULT_YELLOW_STATES
  @reset_time = reset_time || DEFAULT_RESET_TIME
  @on_health_change = on_health_change
  @min_n_level = 0
  endpoints.each { |ep| @endpoints[ep] = {:n_level => INITIAL_N_LEVEL, :timestamp => 0} }
end

Instance Method Details

#decrease_state(endpoint, t0, t1) ⇒ Object



62
63
64
# File 'lib/right_support/net/lb/health_check.rb', line 62

def decrease_state(endpoint, t0, t1)
  update_state(endpoint, -1, t1) unless @endpoints[endpoint][:n_level] == 0
end

#get_statsObject

Returns a hash of endpoints and their colored health status Useful for logging and debugging



91
92
93
94
95
# File 'lib/right_support/net/lb/health_check.rb', line 91

def get_stats
  stats = {}
  @endpoints.each { |k, v| stats[k] = state_color(v[:n_level]) }
  stats
end

#increase_state(endpoint, t0, t1) ⇒ Object



66
67
68
# File 'lib/right_support/net/lb/health_check.rb', line 66

def increase_state(endpoint, t0, t1)
  update_state(endpoint, 1, t1) unless @endpoints[endpoint][:n_level] == @yellow_states
end

#inspectObject



45
46
47
# File 'lib/right_support/net/lb/health_check.rb', line 45

def inspect
  "<#{self.class.name}: #{get_stats.inspect}>"
end

#loggerObject

Return the logger that our surrounding policy uses



107
108
109
# File 'lib/right_support/net/lb/health_check.rb', line 107

def logger
  @policy.logger
end

#state_color(n_level) ⇒ Object



82
83
84
85
86
87
# File 'lib/right_support/net/lb/health_check.rb', line 82

def state_color(n_level)
  color = 'green' if n_level == 0
  color = 'red' if n_level >= @yellow_states
  color = "yellow-#{n_level}" if n_level > 0 && n_level < @yellow_states
  color
end

#sweepObject



53
54
55
# File 'lib/right_support/net/lb/health_check.rb', line 53

def sweep
  @endpoints.each { |k,v| decrease_state(k, 0, Time.now) if Float(Time.now - v[:timestamp]) > @reset_time }
end

#sweep_and_return_yellow_and_greenObject



57
58
59
60
# File 'lib/right_support/net/lb/health_check.rb', line 57

def sweep_and_return_yellow_and_green
  sweep
  @endpoints.select { |k,v| v[:n_level] < @yellow_states }
end

#to_sObject



49
50
51
# File 'lib/right_support/net/lb/health_check.rb', line 49

def to_s
  inspect
end

#update!(new_endpoints) ⇒ Object

Replace the set of endpoints that this object knows about. If any endpoint in the new set is already being tracked, remember its health. For any new endpoint, set its health to INITIAL_N_LEVEL.



101
102
103
104
# File 'lib/right_support/net/lb/health_check.rb', line 101

def update!(new_endpoints)
  @endpoints.each { |k,v| new_endpoints.include?(k) ? new_endpoints.delete(k) : @endpoints.delete(k) }
  new_endpoints.each  { |ep| @endpoints[ep] = {:n_level => INITIAL_N_LEVEL, :timestamp => 0} }
end

#update_state(endpoint, change, t1) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/right_support/net/lb/health_check.rb', line 70

def update_state(endpoint, change, t1)
  @endpoints[endpoint][:timestamp] = t1
  n_level = @endpoints[endpoint][:n_level] += change
  logger.info("RequestBalancer: Health of endpoint '#{endpoint}' #{change < 0 ? 'improved' : 'worsened'} to '#{state_color(n_level)}'")
  if @on_health_change &&
     (n_level < @min_n_level ||
     (n_level > @min_n_level && n_level == @endpoints.map { |(k, v)| v[:n_level] }.min))
    @min_n_level = n_level
    @on_health_change.call(state_color(n_level))
  end
end