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
96
# File 'lib/right_support/net/lb/health_check.rb', line 91

def get_stats
  @endpoints.inject({}) do |stats, (k, v)|
    stats[k] = state_color(v[:n_level])
    stats
  end
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



109
110
111
# File 'lib/right_support/net/lb/health_check.rb', line 109

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.



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

def update!(new_endpoints)
  new_endpoints = new_endpoints.dup # duplicate the array, so we don't modify the passed one.
  @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