Class: HerokuMongoWatcher::Autoscaler

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/heroku_mongo_watcher/autoscaler.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeAutoscaler

Returns a new instance of Autoscaler.



10
11
12
13
# File 'lib/heroku_mongo_watcher/autoscaler.rb', line 10

def initialize()
  @last_scaled = Time.now - 60
  @options = default_options.merge(config)
end

Instance Attribute Details

#last_scaledObject (readonly)

Returns the value of attribute last_scaled.



8
9
10
# File 'lib/heroku_mongo_watcher/autoscaler.rb', line 8

def last_scaled
  @last_scaled
end

#optionsObject (readonly)

Returns the value of attribute options.



8
9
10
# File 'lib/heroku_mongo_watcher/autoscaler.rb', line 8

def options
  @options
end

Instance Method Details

#configObject



25
26
27
# File 'lib/heroku_mongo_watcher/autoscaler.rb', line 25

def config
  HerokuMongoWatcher::Configuration.instance.config
end

#default_optionsObject



15
16
17
18
19
20
21
22
23
# File 'lib/heroku_mongo_watcher/autoscaler.rb', line 15

def default_options
  {
      min_dynos: 6,
      max_dynos: 50,
      step: 5,
      requests_per_dyno: 1000,
      min_frequency: 60 # seconds
  }
end

#herokuObject



72
73
74
# File 'lib/heroku_mongo_watcher/autoscaler.rb', line 72

def heroku
  @heroku ||= Heroku::Client.new(config[:heroku_username], config[:heroku_password])
end

#scale(data_row) ⇒ Object

should play it safe and add config to the calculated result if rpm > 10,000 scale to 15 if rpm > 15,000 scale to 20 if rpm > 20,000 scale to 25 if rpm then drops to 14,000 drop to 15 if rpm then drops to 300 drop to 6 (minimum)

also do not scale down for 5 minutes always allow to scale up



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/heroku_mongo_watcher/autoscaler.rb', line 38

def scale(data_row)

  rpm = data_row.total_requests
  current_dynos = data_row.dynos

  # 32,012 rpm => 32 dynos
  ideal_dynos = (rpm / options[:requests_per_dyno]).round

  # return if the delta is less than 5 dynos | don't think I need to do this ...
  #return if (ideal_dynos - current_dynos).abs < options[:step]

  #this turns 32 into 30
  stepped_dynos = (ideal_dynos/options[:step]).round * options[:step]

  #this turns 30 into 35
  stepped_dynos += options[:step]

  #this makes sure that it stays within the min max bounds
  stepped_dynos = options[:min_dynos] if stepped_dynos < options[:min_dynos]
  stepped_dynos = options[:max_dynos] if stepped_dynos > options[:max_dynos]

  # Don't allow downscaling until 5 minutes
  if stepped_dynos < current_dynos && (Time.now - last_scaled) < (60 * 60) # 1 hour
    #puts ">> Current: [#{current_dynos}], Ideal: [#{stepped_dynos}] | will not downscale within an hour"
    nil
  elsif stepped_dynos != current_dynos
    set_dynos(stepped_dynos)
    stepped_dynos
  else
    nil
  end

end

#set_dynos(count) ⇒ Object



76
77
78
79
80
81
82
83
# File 'lib/heroku_mongo_watcher/autoscaler.rb', line 76

def set_dynos(count)
  @last_scaled = Time.now
  t = Thread.new('Setting Dynos') do
    i = heroku.ps_scale(config[:heroku_appname], :type => 'web', :qty => count)
  end
  t.join

end