Class: Sidekiq::HerokuAutoscale::ScaleStrategy

Inherits:
Object
  • Object
show all
Defined in:
lib/sidekiq/heroku_autoscale/scale_strategy.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mode: :binary, max_dynos: 1, workers_per_dyno: 25, min_factor: 0) ⇒ ScaleStrategy

Returns a new instance of ScaleStrategy.



7
8
9
10
11
12
# File 'lib/sidekiq/heroku_autoscale/scale_strategy.rb', line 7

def initialize(mode: :binary, max_dynos: 1, workers_per_dyno: 25, min_factor: 0)
  @mode = mode
  @max_dynos = max_dynos
  @workers_per_dyno = workers_per_dyno
  @min_factor = min_factor
end

Instance Attribute Details

#max_dynosObject

Returns the value of attribute max_dynos.



5
6
7
# File 'lib/sidekiq/heroku_autoscale/scale_strategy.rb', line 5

def max_dynos
  @max_dynos
end

#min_factorObject

Returns the value of attribute min_factor.



5
6
7
# File 'lib/sidekiq/heroku_autoscale/scale_strategy.rb', line 5

def min_factor
  @min_factor
end

#modeObject

Returns the value of attribute mode.



5
6
7
# File 'lib/sidekiq/heroku_autoscale/scale_strategy.rb', line 5

def mode
  @mode
end

#workers_per_dynoObject

Returns the value of attribute workers_per_dyno.



5
6
7
# File 'lib/sidekiq/heroku_autoscale/scale_strategy.rb', line 5

def workers_per_dyno
  @workers_per_dyno
end

Instance Method Details

#binary(sys) ⇒ Object



23
24
25
# File 'lib/sidekiq/heroku_autoscale/scale_strategy.rb', line 23

def binary(sys)
  sys.has_work? ? @max_dynos : 0
end

#call(sys) ⇒ Object



14
15
16
17
18
19
20
21
# File 'lib/sidekiq/heroku_autoscale/scale_strategy.rb', line 14

def call(sys)
  case @mode.to_s
  when 'linear'
    linear(sys)
  else
    binary(sys)
  end
end

#linear(sys) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/sidekiq/heroku_autoscale/scale_strategy.rb', line 27

def linear(sys)
  # total capacity of max workers
  total_capacity = (@max_dynos * @workers_per_dyno).to_f

  # min capacity required to scale first worker
  min_capacity = [0, @min_factor].max.to_f * @workers_per_dyno

  # min percentage of total capacity
  min_capacity_percentage = min_capacity / total_capacity
  requested_capacity_percentage = sys.total_work / total_capacity

  # Scale requested capacity taking into account the minimum required
  scale_factor = (requested_capacity_percentage - min_capacity_percentage) / (total_capacity - min_capacity_percentage)
  scale_factor = 0 if scale_factor.nan? # Handle DIVZERO
  scaled_capacity_percentage = scale_factor * total_capacity

  # don't scale down past number of currently engaged workers,
  # and don't scale up past maximum dynos
  ideal_dynos = ([0, scaled_capacity_percentage].max * @max_dynos).ceil
  minimum_dynos = [sys.dynos, ideal_dynos].max
  maximum_dynos = [minimum_dynos, @max_dynos].min
  [minimum_dynos, maximum_dynos].min
end