Class: HerokuVector::DynoScaler
- Inherits:
-
Object
- Object
- HerokuVector::DynoScaler
- Includes:
- Helper
- Defined in:
- lib/heroku_vector/dyno_scaler.rb
Constant Summary collapse
- MIN_SCALE_TIME_DELTA_SEC =
5 mins
5 * 60
Instance Attribute Summary collapse
-
#engine ⇒ Object
readonly
Returns the value of attribute engine.
-
#last_scale_time ⇒ Object
Returns the value of attribute last_scale_time.
-
#max_dynos ⇒ Object
readonly
Returns the value of attribute max_dynos.
-
#max_value ⇒ Object
readonly
Returns the value of attribute max_value.
-
#min_dynos ⇒ Object
readonly
Returns the value of attribute min_dynos.
-
#min_value ⇒ Object
readonly
Returns the value of attribute min_value.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#period ⇒ Object
readonly
Returns the value of attribute period.
-
#sampler ⇒ Object
readonly
Returns the value of attribute sampler.
-
#scale_down_by ⇒ Object
readonly
Returns the value of attribute scale_down_by.
-
#scale_up_by ⇒ Object
readonly
Returns the value of attribute scale_up_by.
-
#source ⇒ Object
Returns the value of attribute source.
Instance Method Summary collapse
- #collect_sample ⇒ Object
- #current_size ⇒ Object
- #current_value ⇒ Object
- #display_unit ⇒ Object
- #enough_samples? ⇒ Boolean
- #evaluate_and_scale ⇒ Object
-
#initialize(name, options = {}) ⇒ DynoScaler
constructor
A new instance of DynoScaler.
- #load_data_source(options) ⇒ Object
- #normalize_dyno_increment(amount) ⇒ Object
- #record_last_scale_event ⇒ Object
- #reset ⇒ Object
- #run ⇒ Object
- #scale_dynos(current_amount, new_amount) ⇒ Object
- #scaling_too_soon? ⇒ Boolean
Methods included from Helper
Constructor Details
#initialize(name, options = {}) ⇒ DynoScaler
Returns a new instance of DynoScaler.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 13 def initialize(name, ={}) @name = name @period = [:period] || 60 # 1 min sample_size = [:sample_size] || Sampler.capacity_for_sample_period(@period) @sampler = Sampler.new( sample_size ) @min_dynos = [:min_dynos] || 2 @max_dynos = [:max_dynos] || 10 @min_value = [:min_value] || raise("DynoScaler: min_value required") @max_value = [:max_value] || raise("DynoScaler: max_value required") @scale_up_by = [:scale_up_by] || 1 @scale_down_by = [:scale_down_by] || 1 @source = load_data_source() @engine = [:engine] || Engine::Heroku.new end |
Instance Attribute Details
#engine ⇒ Object (readonly)
Returns the value of attribute engine.
8 9 10 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 8 def engine @engine end |
#last_scale_time ⇒ Object
Returns the value of attribute last_scale_time.
7 8 9 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 7 def last_scale_time @last_scale_time end |
#max_dynos ⇒ Object (readonly)
Returns the value of attribute max_dynos.
8 9 10 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 8 def max_dynos @max_dynos end |
#max_value ⇒ Object (readonly)
Returns the value of attribute max_value.
8 9 10 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 8 def max_value @max_value end |
#min_dynos ⇒ Object (readonly)
Returns the value of attribute min_dynos.
8 9 10 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 8 def min_dynos @min_dynos end |
#min_value ⇒ Object (readonly)
Returns the value of attribute min_value.
8 9 10 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 8 def min_value @min_value end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
8 9 10 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 8 def name @name end |
#period ⇒ Object (readonly)
Returns the value of attribute period.
8 9 10 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 8 def period @period end |
#sampler ⇒ Object (readonly)
Returns the value of attribute sampler.
8 9 10 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 8 def sampler @sampler end |
#scale_down_by ⇒ Object (readonly)
Returns the value of attribute scale_down_by.
8 9 10 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 8 def scale_down_by @scale_down_by end |
#scale_up_by ⇒ Object (readonly)
Returns the value of attribute scale_up_by.
8 9 10 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 8 def scale_up_by @scale_up_by end |
#source ⇒ Object
Returns the value of attribute source.
7 8 9 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 7 def source @source end |
Instance Method Details
#collect_sample ⇒ Object
89 90 91 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 89 def collect_sample sampler << source.sample end |
#current_size ⇒ Object
93 94 95 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 93 def current_size engine.count_for_dyno_name(self.name) end |
#current_value ⇒ Object
85 86 87 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 85 def current_value sampler.mean end |
#display_unit ⇒ Object
128 129 130 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 128 def display_unit source.unit rescue 'units' end |
#enough_samples? ⇒ Boolean
117 118 119 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 117 def enough_samples? sampler.full? end |
#evaluate_and_scale ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 61 def evaluate_and_scale num_dynos = current_size total_min = min_value * num_dynos total_max = max_value * num_dynos value = current_value logger.debug "#{self.name}: #{num_dynos} dynos - #{value} #{display_unit}" if value < total_min unless num_dynos <= min_dynos logger.info "#{self.name}: #{num_dynos} dynos - #{value} #{display_unit} below #{total_min} - scaling down" end # Always scale down one at a time new_amount = num_dynos - scale_down_by scale_dynos(num_dynos, new_amount) elsif value > total_max unless num_dynos >= max_dynos logger.info "#{self.name}: #{num_dynos} dynos - #{value} #{display_unit} above #{total_max} - scaling up" end # Scale up to N new dynos new_amount = num_dynos + scale_up_by scale_dynos(num_dynos, new_amount) end end |
#load_data_source(options) ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 29 def load_data_source() source = [:source] if source.is_a?(Class) @source = source.new() else begin clazz = HerokuVector::Source.const_get(source) @source = clazz.new() rescue raise "DynoScaler: Invalid source class '#{source}'" end end end |
#normalize_dyno_increment(amount) ⇒ Object
106 107 108 109 110 111 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 106 def normalize_dyno_increment(amount) [ [amount, max_dynos].min, min_dynos ].max end |
#record_last_scale_event ⇒ Object
113 114 115 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 113 def record_last_scale_event @last_scale_time = Time.now end |
#reset ⇒ Object
44 45 46 47 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 44 def reset sampler.clear @last_scale_time = nil end |
#run ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 49 def run begin collect_sample return unless enough_samples? return if scaling_too_soon? evaluate_and_scale rescue => e logger.error "#{self.name} worker.run(): #{e}" end end |
#scale_dynos(current_amount, new_amount) ⇒ Object
97 98 99 100 101 102 103 104 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 97 def scale_dynos(current_amount, new_amount) new_amount = normalize_dyno_increment(new_amount) return if current_amount == new_amount record_last_scale_event engine.scale_dynos(self.name, new_amount) end |
#scaling_too_soon? ⇒ Boolean
121 122 123 124 125 126 |
# File 'lib/heroku_vector/dyno_scaler.rb', line 121 def scaling_too_soon? return false unless last_scale_time scale_delta = Time.now - last_scale_time MIN_SCALE_TIME_DELTA_SEC >= scale_delta end |