Class: Wordnik::LoadBalancer

Inherits:
Object
  • Object
show all
Defined in:
lib/wordnik/load_balancer.rb

Overview

These should be thread safe.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hosts) ⇒ LoadBalancer

Returns a new instance of LoadBalancer.



21
22
23
24
25
26
27
# File 'lib/wordnik/load_balancer.rb', line 21

def initialize(hosts)
  @all_hosts = hosts.clone
  @hosts = @all_hosts.clone
  @failed_hosts_table = {}
  @current_host = nil
  Wordnik.logger.info "LoadBalancer: Creating a load balancer using the following hosts: #{@hosts.join(', ')}"
end

Instance Attribute Details

#all_hostsObject

Returns the value of attribute all_hosts.



17
18
19
# File 'lib/wordnik/load_balancer.rb', line 17

def all_hosts
  @all_hosts
end

#current_hostObject

Returns the value of attribute current_host.



19
20
21
# File 'lib/wordnik/load_balancer.rb', line 19

def current_host
  @current_host
end

#failed_hosts_tableObject

Returns the value of attribute failed_hosts_table.



18
19
20
# File 'lib/wordnik/load_balancer.rb', line 18

def failed_hosts_table
  @failed_hosts_table
end

#hostsObject (readonly)

Returns the value of attribute hosts.



16
17
18
# File 'lib/wordnik/load_balancer.rb', line 16

def hosts
  @hosts
end

Instance Method Details

#hostObject



29
30
31
32
33
34
# File 'lib/wordnik/load_balancer.rb', line 29

def host
  @current_host = hosts.first
  @hosts.rotate!
  restore_failed_hosts_maybe
  @current_host
end

#inform_failureObject



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/wordnik/load_balancer.rb', line 36

def inform_failure
    #Wordnik.logger.debug "Informing failure about #{@current_host}. table: #{@failed_hosts_table.inspect}"
  if @failed_hosts_table.include?(@current_host)
    failures, failed_time = @failed_hosts_table[@current_host]
    @failed_hosts_table[@current_host] = [failures+1, Time.now.to_f]
  else
    @failed_hosts_table[@current_host] = [1, Time.now.to_f] # failure count, first failure time
  end
  #Wordnik.logger.debug "Informed failure about #{@current_host}. table now: #{@failed_hosts_table.inspect}"
  @hosts.delete(@current_host)
  @hosts = [@current_host] if @hosts.size == 0 # got to have something!
  if @hosts == [@current_host]
    Wordnik.logger.warn "LoadBalancer: host #{@current_host} failed, but it is the only remaining host. Not removing."
  else
    Wordnik.logger.info "LoadBalancer: host #{@current_host} failed. Removed from active hosts, which are now: #{@hosts.join(', ')}"
  end
end

#inform_successObject

success here means just that a successful connection was made and the website didn’t time out.



56
57
58
59
60
61
# File 'lib/wordnik/load_balancer.rb', line 56

def inform_success
  @failed_hosts_table.delete(@current_host)
  @hosts << @current_host unless @hosts.include? @current_host
  Wordnik.logger.info "LoadBalancer: host #{@current_host} is working again, and has been added to active hosts, which are now: #{@hosts.join(', ')}"
  @hosts
end

#restore_failed_hosts_maybeObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/wordnik/load_balancer.rb', line 63

def restore_failed_hosts_maybe
  return if @failed_hosts_table.size == 0
  @failed_hosts_table.each do |host, pair|
    failures, failed_time = pair
    n = Time.now.to_f
    seconds_since_last_failure = (n - failed_time)
    # exponential backoff, but try every hour...
    if (seconds_since_last_failure > [3600, 2**(failures-1)].min)
      @hosts << host # give it a chance to succeed ...
      Wordnik.logger.info "LoadBalancer: timeout for host #{host} failure exceeded; returning to active hosts, which are now: #{@hosts.join(', ')}"
      update_failed_time(host, n)
    end
  end
end

#update_failed_time(host, time = Time.now) ⇒ Object

mostly useful in mock testing…



79
80
81
82
83
84
85
86
# File 'lib/wordnik/load_balancer.rb', line 79

def update_failed_time(host, time=Time.now)
  if @failed_hosts_table.include? host
    failures, _ = @failed_hosts_table[host]
    @failed_hosts_table[host] = [failures, time.to_f]
  else
  @failed_hosts_table[host] = [1,time.to_f]
  end
end