Class: HAProxyCluster

Inherits:
Object
  • Object
show all
Defined in:
lib/haproxy_cluster/stats_container.rb,
lib/haproxy_cluster.rb,
lib/haproxy_cluster/member.rb,
lib/haproxy_cluster/server.rb,
lib/haproxy_cluster/backend.rb,
lib/haproxy_cluster/version.rb

Overview

Backends present summary statistics for the servers they contain, and individual servers also present their own specific data.

Defined Under Namespace

Classes: Backend, Member, Server, StatsContainer

Constant Summary collapse

Inf =
+1.0/0.0
NegInf =
-1.0/0.0
VERSION =
"0.0.7"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(members = [], log_level = Logger::INFO) ⇒ HAProxyCluster

Returns a new instance of HAProxyCluster.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/haproxy_cluster.rb', line 11

def initialize(members = [], log_level = Logger::INFO)
  @members = []
  @log = Logger.new(STDOUT)
  pp log_level
  log.level = log_level
  original_formatter = Logger::Formatter.new
  @log.formatter = proc { |severity,datetime,progname,msg|
    original_formatter.call(severity,datetime,self.class.to_s,msg)
  }
  threads = []
  members.each do |url|
    threads << Thread.new do
      @members << HAProxyCluster::Member.new(url,@log)
    end
  end
  threads.each{|t|t.join}
end

Instance Attribute Details

#logObject

Returns the value of attribute log.



29
30
31
# File 'lib/haproxy_cluster.rb', line 29

def log
  @log
end

#membersObject

Returns the value of attribute members.



29
30
31
# File 'lib/haproxy_cluster.rb', line 29

def members
  @members
end

Instance Method Details

#check_condition(condition, values) ⇒ Object

Return true or false depending on the relationship between ‘condition` and `values`. `condition` may be specified as true, false, or a Range object. `values` is an Array of whatever type is appropriate for the condition.

check_condition(0!=1,   [true])         #=> true
check_condition(1==1,   [true])         #=> true
check_condition(3..Inf, [2,2])          #=> false
check_condition(true,   [true,false])   #=> raise Timeout::timeout


117
118
119
120
121
122
123
124
125
126
127
# File 'lib/haproxy_cluster.rb', line 117

def check_condition (condition, values)
  case condition.class.to_s
  when "Range"
    values.each{ |v| return false unless condition.cover? v }
  when "TrueClass", "FalseClass" 
    values.each{ |v| return false unless v == condition }
  else
    raise ArgumentError.new("Got #{condition.class.to_s} but TrueClass, FalseClass, or Range expected")
  end
  return true
end

#each_member(&code) ⇒ Object

Run the specified code against every memeber of the cluster. Results are returned as a Hash, with member.to_s being the key.



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/haproxy_cluster.rb', line 97

def each_member (&code)
  threads = []
  results = {}
  @members.each do |member|
    threads << Thread.new do
      results[member.to_s] = member.instance_exec &code
    end
  end
  threads.each{|t|t.join}
  return results
end

#poll(interval = 1.0) ⇒ Object

Poll the cluster, executing the given block with fresh data at the prescribed interval.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/haproxy_cluster.rb', line 33

def poll(interval = 1.0)
  first = true
  loop do
    start = Time.now
    each_member { poll! } unless first
    first = false
    yield
    delay = Time.now - start
    if delay >= interval
      sleep interval
    else
      sleep interval - delay
    end
  end
end

#wait_until(options = {}, &code) ⇒ Object

Poll the entire cluster until the the given block’s return value always matches the condition (expressed as boolean or range).

This block would not return until every member of the cluster is available to serve requests.

wait_for(:condition => true) do
  api.servers.map{|s|s.ok?}
end

The constants ‘Inf` and `NegInf` (representing infinity and negative infinity respectively) are available, which enables less than/greater than expressions in the form of `Range`s.

Parameters:

  • :condition, anything accepted by ‘check_condition`

  • :interval, check interval (default 2 seconds, same as HA Proxy)

  • :timeout, give up after this number of seconds

  • :min_checks, require :condition consecutive positive results



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/haproxy_cluster.rb', line 70

def wait_until (options = {}, &code)
  opts = {
    :condition => true,
    :interval => 2.0,
    :timeout => 300,
    :min_checks => 3
  }.merge options
  Timeout::timeout(opts[:timeout]) do
    history = []
    loop do
      results = each_member(&code)

      # Break out as soon as we reach :min_checks in a row
      history << check_condition(opts[:condition], results.values.flatten)
      if history.last(opts[:min_checks]) == [true] * opts[:min_checks]
        log.info { "Ok, we've seen #{opts[:min_checks]} consecutive successful results." }
        return true
      end

      sleep opts[:interval]
      each_member { poll! }
    end
  end
end