our-eel-hacks 0.0.15 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: