Class: Heroku::Scalr::App

Inherits:
Object
  • Object
show all
Defined in:
lib/heroku/scalr/app.rb

Constant Summary collapse

DEFAULTS =
{
  interval: 30,
  min_dynos: 1,
  max_dynos: 2,
  wait_low: 10,
  wait_high: 100,
  ping_low: 200,
  ping_high: 500,
  metric: :ping,
  cool_freq: 180,
  heat_freq: 60,
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, opts = {}) ⇒ App

Returns a new instance of App.

Parameters:

  • name (String)

    Heroku app name

  • opts (Hash) (defaults to: {})

    options

Options Hash (opts):

  • :interval (Integer)

    perform checks every ‘interval` seconds, default: 60

  • :min_dynos (Integer)

    the minimum number of dynos, default: 1

  • :max_dynos (Integer)

    the maximum number of dynos, default: 2

  • :wait_low (Integer)

    lowers the number of dynos if queue wait time is less than ‘wait_low` ms, default: 10

  • :wait_high (Integer)

    lowers the number of dynos if queue wait time is more than ‘wait_high` ms, default: 100

  • :ping_low (Integer)

    lowers the number of dynos if ping time is less than ‘ping_low` ms, default: 200

  • :ping_high (Integer)

    lowers the number of dynos if ping time is more than ‘ping_high` ms, default: 500

  • :cool_freq (Integer)

    leave at least ‘cool_freq` seconds before scaling down again, default: 180

  • :heat_freq (Integer)

    leave at least ‘heat_freq` seconds before scaling up again, default: 60

  • :api_key (String)

    the Heroku account’s API key



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/heroku/scalr/app.rb', line 42

def initialize(name, opts = {})
  @name = name.to_s

  opts = DEFAULTS.merge(opts)
  fail("no API key given") unless opts[:api_key]
  fail("min_dynos must be at least 1") unless opts[:min_dynos] >= 1
  fail("max_dynos must be at least 1") unless opts[:max_dynos] >= 1
  fail("interval must be at least 10") unless opts[:interval] >= 10

  @url       = opts[:url] || "http://#{@name}.herokuapp.com/robots.txt"
  @api_key   = opts[:api_key]
  @interval  = opts[:interval].to_i
  @min_dynos = opts[:min_dynos].to_i
  @max_dynos = opts[:max_dynos].to_i
  @wait_low  = opts[:wait_low].to_i
  @wait_high = opts[:wait_high].to_i
  @ping_low  = opts[:ping_low].to_i
  @ping_high = opts[:ping_high].to_i
  @metric    = Heroku::Scalr::Metric.new(opts[:metric], self)
  @cool_freq = opts[:cool_freq].to_i
  @heat_freq = opts[:heat_freq].to_i
  @last_scaled_at = Time.at(0)
end

Instance Attribute Details

#api_keyObject (readonly)

Returns the value of attribute api_key.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def api_key
  @api_key
end

#cool_freqObject (readonly)

Returns the value of attribute cool_freq.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def cool_freq
  @cool_freq
end

#heat_freqObject (readonly)

Returns the value of attribute heat_freq.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def heat_freq
  @heat_freq
end

#intervalObject (readonly)

Returns the value of attribute interval.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def interval
  @interval
end

#last_scaled_atObject (readonly)

Returns the value of attribute last_scaled_at.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def last_scaled_at
  @last_scaled_at
end

#max_dynosObject (readonly)

Returns the value of attribute max_dynos.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def max_dynos
  @max_dynos
end

#metricObject (readonly)

Returns the value of attribute metric.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def metric
  @metric
end

#min_dynosObject (readonly)

Returns the value of attribute min_dynos.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def min_dynos
  @min_dynos
end

#nameObject (readonly)

Returns the value of attribute name.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def name
  @name
end

#ping_highObject (readonly)

Returns the value of attribute ping_high.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def ping_high
  @ping_high
end

#ping_lowObject (readonly)

Returns the value of attribute ping_low.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def ping_low
  @ping_low
end

#urlObject (readonly)

Returns the value of attribute url.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def url
  @url
end

#wait_highObject (readonly)

Returns the value of attribute wait_high.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def wait_high
  @wait_high
end

#wait_lowObject (readonly)

Returns the value of attribute wait_low.



16
17
18
# File 'lib/heroku/scalr/app.rb', line 16

def wait_low
  @wait_low
end

Instance Method Details

#log(level, message) ⇒ Object

Parameters:

  • level (Symbol)
  • message (String)


86
87
88
# File 'lib/heroku/scalr/app.rb', line 86

def log(level, message)
  Heroku::Scalr.logger.send(level, "[#{name}] #{message}")
end

#scale!Object

Scales the app



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/heroku/scalr/app.rb', line 67

def scale!
  scale_at = last_scaled_at + [cool_freq, heat_freq].min
  now      = Time.now
  if now < scale_at
    log :debug, "skip check, next attempt in #{(scale_at - now).to_i}s"
    return
  end

  by = metric.by
  do_scale(by) if must_scale?(by, now)
rescue => e
  msg = "#{e.class}: #{e.to_s}"
  msg << "\n\t" << e.backtrace.join("\n\t") if e.backtrace
  log :error, msg
  nil
end