our-eel-hacks 0.0.15 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- require 'heroku'
1
+ require 'our-eel-hacks/heroku-client'
2
2
 
3
3
  module OurEelHacks
4
4
  class NullLogger
@@ -132,8 +132,11 @@ module OurEelHacks
132
132
  end
133
133
 
134
134
  API_CALLS_PER_SCALE = 2
135
- def scale(metric)
136
- logger.debug{ "Scaling request for #{@ps_type}: metric is: #{metric}" }
135
+ def scale(metric_hash)
136
+ logger.debug{ "Scaling request for #{@ps_type}: metrics are: #{metric_hash.inspect}" }
137
+
138
+ #TODO: multi-metric scaling logic
139
+ metric = metric_hash.to_a.last.last #Yeah, this is awful
137
140
  moment = Time.now
138
141
  if elapsed(last_scaled, moment) < millis_til_next_scale
139
142
  logger.debug{ "Not scaling: elapsed #{elapsed(last_scaled, moment)} less than computed #{millis_til_next_scale}" }
@@ -232,11 +235,7 @@ module OurEelHacks
232
235
  end
233
236
 
234
237
  def heroku
235
- @heroku ||= Heroku::Client.new("", heroku_api_key).tap do |client|
236
- unless client.info(app_name)[:stack] == "cedar"
237
- raise "#{self.class.name} built against cedar stack"
238
- end
239
- end
238
+ @heroku ||= HerokuClient.new(logger, "", heroku_api_key)
240
239
  end
241
240
 
242
241
  def set_dynos(count,moment)
@@ -4,15 +4,15 @@ module OurEelHacks
4
4
  class Rack < Middleware
5
5
  include Defer::EventMachine
6
6
 
7
- def initialize(app, env_field, flavor = :web)
7
+ def initialize(app, env_fields, flavor = :web)
8
8
  super(flavor)
9
- @env_field = env_field
9
+ @env_fields = [*env_fields].map(&:to_s)
10
10
  @app = app
11
11
  end
12
12
 
13
13
  def call(env)
14
14
  begin
15
- autoscale(metric_from(env))
15
+ autoscale(metrics_from(env))
16
16
  rescue => ex
17
17
  puts "Problem in autoscaling: #{ex.inspect}"
18
18
  end
@@ -20,10 +20,10 @@ module OurEelHacks
20
20
  @app.call(env)
21
21
  end
22
22
 
23
- def metric_from(env)
24
- (Integer(env[@env_field]) rescue 0).tap{|val|
25
- puts "#{@env_field} => #{env[@env_field]} : #{val}"
26
- }
23
+ def metrics_from(env)
24
+ Hash[ @env_fields.map do |field|
25
+ [field, (Integer(env[field]) rescue 0)]
26
+ end ]
27
27
  end
28
28
  end
29
29
 
@@ -10,7 +10,7 @@ module OurEelHacks
10
10
 
11
11
  def call(worker_class, item, queue)
12
12
  begin
13
- autoscale(get_queue_length(queue).tap{|length| puts "Queue length: #{length}"})
13
+ autoscale(get_queue_length(queue))
14
14
  rescue => ex
15
15
  puts "Problem in autoscaling: #{ex.inspect}"
16
16
  end
@@ -18,9 +18,9 @@ module OurEelHacks
18
18
  end
19
19
 
20
20
  def get_queue_length(queue)
21
- ::Sidekiq.redis do |conn|
21
+ {"queue_length" => ::Sidekiq.redis do |conn|
22
22
  conn.llen("queue:#{queue}") || 0
23
- end
23
+ end }
24
24
  end
25
25
  end
26
26
  end
data/spec/autoscaler.rb CHANGED
@@ -25,23 +25,23 @@ describe OurEelHacks::Autoscaler do
25
25
  end
26
26
 
27
27
  let :ideal_value do
28
- 25
28
+ { "metric" => 25 }
29
29
  end
30
30
 
31
31
  let :soft_high do
32
- 35
32
+ { "metric" => 35 }
33
33
  end
34
34
 
35
35
  let :soft_low do
36
- 3
36
+ { "metric" => 3 }
37
37
  end
38
38
 
39
39
  let :hard_high do
40
- 100
40
+ { "metric" => 100 }
41
41
  end
42
42
 
43
43
  let :hard_low do
44
- -10
44
+ { "metric" => -10 }
45
45
  end
46
46
 
47
47
  let :dyno_count do
@@ -89,6 +89,8 @@ describe OurEelHacks::Autoscaler do
89
89
  test.upper_limits.soft = 30
90
90
  test.upper_limits.hard = 50
91
91
 
92
+ #JDL: useful for debugging spec fails
93
+ #Irritating in general use
92
94
  #test.logger = logger
93
95
  end
94
96
  end
@@ -103,17 +105,26 @@ describe OurEelHacks::Autoscaler do
103
105
  end
104
106
 
105
107
  before :each do
108
+ OurEelHacks::HerokuClient.processing_budget = 3
106
109
  heroku.stub!(:ps_scale)
107
110
  time_adjust(0)
108
111
  autoscaler.scale(ideal_value)
109
112
  end
110
113
 
114
+ def no_requests
115
+ OurEelHacks::HerokuClient.processing_budget = 0
116
+ heroku.should_not_receive(:ps_scale)
117
+ end
118
+
111
119
  describe "scaling frequency" do
112
120
 
113
121
  it "should not scale too soon" do
114
122
  time_adjust(expected_scale_frequency - 5)
115
123
 
116
- heroku.should_not_receive(:ps_scale)
124
+ no_requests
125
+ autoscaler.scale(hard_high)
126
+ autoscaler.scale(hard_high)
127
+ autoscaler.scale(hard_high)
117
128
  autoscaler.scale(hard_high)
118
129
  end
119
130
 
@@ -163,15 +174,19 @@ describe OurEelHacks::Autoscaler do
163
174
  describe "if soft_duration hasn't elapsed" do
164
175
  before :each do
165
176
  time_adjust((expected_scale_frequency * 2) + soft_dur - 5)
166
- heroku.should_not_receive(:ps_scale)
177
+ no_requests
167
178
  end
168
179
 
169
180
  it "should not scale up" do
170
181
  autoscaler.scale(soft_high)
182
+ autoscaler.scale(soft_high)
183
+ autoscaler.scale(soft_high)
171
184
  end
172
185
 
173
186
  it "should not scale down" do
174
187
  autoscaler.scale(soft_low)
188
+ autoscaler.scale(soft_high)
189
+ autoscaler.scale(soft_high)
175
190
  end
176
191
  end
177
192
 
data/spec/rack.rb CHANGED
@@ -12,6 +12,7 @@ describe OurEelHacks::Rack do
12
12
  end
13
13
 
14
14
  before :each do
15
+ OurEelHacks::HerokuClient.processing_budget = 3
15
16
  OurEelHacks::Autoscaler.configure(:test) do |test|
16
17
  test.app_name = app_name
17
18
  test.heroku_api_key = api_key
@@ -35,7 +36,7 @@ describe OurEelHacks::Rack do
35
36
 
36
37
 
37
38
  it "should pass the metric to the autoscaler" do
38
- OurEelHacks::Autoscaler.instance_for(:test).should_receive(:scale).with(100)
39
+ OurEelHacks::Autoscaler.instance_for(:test).should_receive(:scale).with({env_field => 100})
39
40
  middleware.call({env_field => "100"})
40
41
  end
41
42
  end
@@ -12,6 +12,23 @@ RSpec.configure do |config|
12
12
  config.extend VCR::RSpec::Macros
13
13
  end
14
14
 
15
+ require 'our-eel-hacks/heroku-client'
16
+ class OurEelHacks::HerokuClient
17
+ alias real_process process
18
+
19
+ class << self
20
+ attr_accessor :processing_budget
21
+ end
22
+
23
+ def process(*args, &block)
24
+ #puts caller.grep %r{#{File::expand_path("../..",__FILE__)}}
25
+ if (self.class.processing_budget -= 1) < 0
26
+ raise "Exhausted processing budget"
27
+ end
28
+ real_process(*args, &block)
29
+ end
30
+ end
31
+
15
32
  $" << "eventmachine"
16
33
 
17
34
  module EventMachine
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: our-eel-hacks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.16
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-24 00:00:00.000000000 Z
12
+ date: 2012-05-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: corundum
16
- requirement: &76665630 !ruby/object:Gem::Requirement
16
+ requirement: &71944990 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.0.1
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *76665630
24
+ version_requirements: *71944990
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: heroku
27
- requirement: &76675340 !ruby/object:Gem::Requirement
27
+ requirement: &71940420 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -36,7 +36,7 @@ dependencies:
36
36
  - 0
37
37
  type: :runtime
38
38
  prerelease: false
39
- version_requirements: *76675340
39
+ version_requirements: *71940420
40
40
  description: ! " Middleware for Rack and Sidekiq to scale heroku.\n\n A heroku process
41
41
  knows everything it needs in order to scale itself. A little configuration, and
42
42
  you're set.\n"
@@ -68,7 +68,7 @@ rdoc_options:
68
68
  - --main
69
69
  - doc/README
70
70
  - --title
71
- - our-eel-hacks-0.0.15 RDoc
71
+ - our-eel-hacks-0.0.16 RDoc
72
72
  require_paths:
73
73
  - lib/
74
74
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -79,7 +79,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
79
  version: '0'
80
80
  segments:
81
81
  - 0
82
- hash: 711289331
82
+ hash: -980070001
83
83
  required_rubygems_version: !ruby/object:Gem::Requirement
84
84
  none: false
85
85
  requirements: