autoscaler 0.14.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +1 -1
- data/examples/complex.rb +3 -3
- data/lib/autoscaler/binary_scaling_strategy.rb +1 -1
- data/lib/autoscaler/delayed_shutdown.rb +1 -1
- data/lib/autoscaler/heroku_platform_scaler.rb +3 -12
- data/lib/autoscaler/linear_scaling_strategy.rb +1 -1
- data/lib/autoscaler/sidekiq/thread_server.rb +1 -1
- data/lib/autoscaler/stub_scaler.rb +0 -2
- data/lib/autoscaler/version.rb +1 -1
- data/spec/autoscaler/binary_scaling_strategy_spec.rb +1 -1
- data/spec/autoscaler/delayed_shutdown_spec.rb +3 -3
- data/spec/autoscaler/linear_scaling_strategy_spec.rb +13 -13
- data/spec/spec_helper.rb +1 -2
- metadata +13 -30
- data/lib/autoscaler/heroku_scaler.rb +0 -85
- data/spec/autoscaler/heroku_scaler_spec.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2178b48972a2f8602b145cd95959d98df9df800a
|
4
|
+
data.tar.gz: 6fa236be6c17027b4283866739df03f45f62d601
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 690808fd62d423dcc2f928f44b0d50f705af9208aac0e38919d380326c40d8e2ee845ef92f4b19b4ffb5e0568f3c934bd1ce5158e329316a78b23c4ae11c6e0f
|
7
|
+
data.tar.gz: a81d4fd5ab0ae14640cd7814c7d2188a9516515e75c6bf3f8496bf66134f97a6cc7a23d45b684c602321b8300daab1c2735752e21e8feeda08c8d08900811444
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.0.0
|
4
|
+
|
5
|
+
Potentially breaking changes
|
6
|
+
|
7
|
+
- Implemented named arguments for several classes. (Breaking if you instantiated these classes with arguments)
|
8
|
+
- `HerokuPlatformScaler`
|
9
|
+
- `BinaryScalingStrategy`
|
10
|
+
- `LinearScalingStrategy`
|
11
|
+
- `DelayedShutdown`
|
12
|
+
- As consequence of above, specifies min ruby version 2.1
|
13
|
+
- Remove depreciated ENV variables `HEROKU_ACCESS_TOKEN` and `HERKOU_APP`
|
14
|
+
- `HerokuScaler` has been removed, as the old API has been disabled by Heroku. (See <https://devcenter.heroku.com/changelog-items/1181>)
|
15
|
+
Consider to use `HerokuPlatformScaler`.
|
16
|
+
|
3
17
|
## 0.14.0
|
4
18
|
|
5
19
|
- Heroku has claimed the `HEROKU_` ENV prefix for Herkou-16 stack. The preferred variables are now `AUTOSCALER_HEROKU_APP` and `AUTOSCALER_HEROKU_ACCESS_TOKEN`. (The complex example has been similarly updated.) The old ENV variables will still be accepted, with a warning, but may be removed in a major release. (HerokuScaler was not updated.)
|
data/README.md
CHANGED
@@ -38,7 +38,7 @@ Install the middleware in your `Sidekiq.configure_` blocks
|
|
38
38
|
|
39
39
|
- HerokuPlatformScaler includes an attempt at current-worker cache that may be overcomplication, and doesn't work very well on the server
|
40
40
|
- Multiple scale-down loops may be started, particularly if there are multiple jobs queued when the servers comes up. Heroku seems to handle multiple scale-down commands well.
|
41
|
-
- The scale-down monitor is triggered on job completion (and server middleware is only run around jobs), so if the server
|
41
|
+
- The scale-down monitor is triggered on job completion (and server middleware is only run around jobs), so if the server never processes any jobs, it won't turn off.
|
42
42
|
- The retry and schedule lists are considered - if you schedule a long-running task, the process will not scale-down.
|
43
43
|
- If background jobs trigger jobs in other scaled processes, please note you'll need `config.client_middleware` in your `Sidekiq.configure_server` block in order to scale-up.
|
44
44
|
- Exceptions while calling the Heroku API are caught and printed by default. See `HerokuPlatformScaler#exception_handler` to override
|
data/examples/complex.rb
CHANGED
@@ -12,9 +12,9 @@ if ENV['AUTOSCALER_HEROKU_APP']
|
|
12
12
|
# We are using the convention that worker process type is the
|
13
13
|
# same as the queue name
|
14
14
|
heroku[queue] = Autoscaler::HerokuPlatformScaler.new(
|
15
|
-
queue,
|
16
|
-
ENV['AUTOSCALER_HEROKU_ACCESS_TOKEN'],
|
17
|
-
ENV['AUTOSCALER_HEROKU_APP'])
|
15
|
+
type: queue,
|
16
|
+
token: ENV['AUTOSCALER_HEROKU_ACCESS_TOKEN'],
|
17
|
+
app: ENV['AUTOSCALER_HEROKU_APP'])
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -3,7 +3,7 @@ module Autoscaler
|
|
3
3
|
# The default strategy has a single worker when there is anything, or shuts it down.
|
4
4
|
class BinaryScalingStrategy
|
5
5
|
#@param [integer] active_workers number of workers when in the active state.
|
6
|
-
def initialize(active_workers
|
6
|
+
def initialize(active_workers: 1)
|
7
7
|
@active_workers = active_workers
|
8
8
|
end
|
9
9
|
|
@@ -3,7 +3,7 @@ module Autoscaler
|
|
3
3
|
class DelayedShutdown
|
4
4
|
# @param [ScalingStrategy] strategy object that makes most decisions
|
5
5
|
# @param [Numeric] timeout number of seconds to stay up after base strategy says zero
|
6
|
-
def initialize(strategy
|
6
|
+
def initialize(strategy:, timeout:)
|
7
7
|
@strategy = strategy
|
8
8
|
@timeout = timeout
|
9
9
|
active_now!
|
@@ -8,18 +8,9 @@ module Autoscaler
|
|
8
8
|
# @param [String] token Heroku OAuth access token
|
9
9
|
# @param [String] app Heroku app name
|
10
10
|
def initialize(
|
11
|
-
type
|
12
|
-
token
|
13
|
-
app
|
14
|
-
|
15
|
-
if (token.nil? && ENV['HEROKU_ACCESS_TOKEN'])
|
16
|
-
warn "Autoscaler: ENV AUTOSCALER_HEROKU_ACCESS_TOKEN is now preferred, HEROKU_ACCESS_TOKEN may be removed in a future release"
|
17
|
-
token = ENV['HEROKU_ACCESS_TOKEN']
|
18
|
-
end
|
19
|
-
if (app.nil? && ENV['HEROKU_APP'])
|
20
|
-
warn "Autoscaler: ENV AUTOSCALER_HEROKU_APP is now preferred, HEROKU_APP may be removed in a future release"
|
21
|
-
app = ENV['HEROKU_APP']
|
22
|
-
end
|
11
|
+
type: 'worker',
|
12
|
+
token: ENV['AUTOSCALER_HEROKU_ACCESS_TOKEN'],
|
13
|
+
app: ENV['AUTOSCALER_HEROKU_APP'])
|
23
14
|
|
24
15
|
@client = PlatformAPI.connect_oauth(token)
|
25
16
|
@type = type
|
@@ -5,7 +5,7 @@ module Autoscaler
|
|
5
5
|
#@param [integer] max_workers maximum number of workers to spin up.
|
6
6
|
#@param [integer] worker_capacity the amount of jobs one worker can handle
|
7
7
|
#@param [float] min_factor minimum work required to scale, as percentage of worker_capacity
|
8
|
-
def initialize(max_workers
|
8
|
+
def initialize(max_workers: 1, worker_capacity: 25, min_factor: 0)
|
9
9
|
@max_workers = max_workers # max # of workers we can scale to
|
10
10
|
@total_capacity = (@max_workers * worker_capacity).to_f # total capacity of max workers
|
11
11
|
min_capacity = [0, min_factor].max.to_f * worker_capacity # min capacity required to scale first worker
|
data/lib/autoscaler/version.rb
CHANGED
@@ -6,17 +6,17 @@ describe Autoscaler::DelayedShutdown do
|
|
6
6
|
let(:cut) {Autoscaler::DelayedShutdown}
|
7
7
|
|
8
8
|
it "returns normal values" do
|
9
|
-
strategy = cut.new(lambda{|s,t| 2}, 0)
|
9
|
+
strategy = cut.new(strategy: lambda{|s,t| 2}, timeout: 0)
|
10
10
|
expect(strategy.call(nil, 1)).to eq 2
|
11
11
|
end
|
12
12
|
|
13
13
|
it "delays zeros" do
|
14
|
-
strategy = cut.new(lambda{|s,t| 0}, 60)
|
14
|
+
strategy = cut.new(strategy: lambda{|s,t| 0}, timeout: 60)
|
15
15
|
expect(strategy.call(nil, 1)).to eq 1
|
16
16
|
end
|
17
17
|
|
18
18
|
it "eventually returns zero" do
|
19
|
-
strategy = cut.new(lambda{|s,t| 0}, 60)
|
19
|
+
strategy = cut.new(strategy: lambda{|s,t| 0}, timeout: 60)
|
20
20
|
allow(strategy).to receive(:level_idle_time).and_return(61)
|
21
21
|
expect(strategy.call(nil, 61)).to eq 0
|
22
22
|
end
|
@@ -7,79 +7,79 @@ describe Autoscaler::LinearScalingStrategy do
|
|
7
7
|
|
8
8
|
it "deactivates with no work" do
|
9
9
|
system = TestSystem.new(0)
|
10
|
-
strategy = cut.new(1)
|
10
|
+
strategy = cut.new(max_workers: 1)
|
11
11
|
expect(strategy.call(system, 1)).to eq 0
|
12
12
|
end
|
13
13
|
|
14
14
|
it "activates with some work" do
|
15
15
|
system = TestSystem.new(1)
|
16
|
-
strategy = cut.new(1)
|
16
|
+
strategy = cut.new(max_workers: 1)
|
17
17
|
expect(strategy.call(system, 1)).to be > 0
|
18
18
|
end
|
19
19
|
|
20
20
|
it "minimally scales with minimal work" do
|
21
21
|
system = TestSystem.new(1)
|
22
|
-
strategy = cut.new(2, 2)
|
22
|
+
strategy = cut.new(max_workers: 2, worker_capacity: 2)
|
23
23
|
expect(strategy.call(system, 1)).to eq 1
|
24
24
|
end
|
25
25
|
|
26
26
|
it "maximally scales with too much work" do
|
27
27
|
system = TestSystem.new(5)
|
28
|
-
strategy = cut.new(2, 2)
|
28
|
+
strategy = cut.new(max_workers: 2, worker_capacity: 2)
|
29
29
|
expect(strategy.call(system, 1)).to eq 2
|
30
30
|
end
|
31
31
|
|
32
32
|
it "proportionally scales with some work" do
|
33
33
|
system = TestSystem.new(5)
|
34
|
-
strategy = cut.new(5, 2)
|
34
|
+
strategy = cut.new(max_workers: 5, worker_capacity: 2)
|
35
35
|
expect(strategy.call(system, 1)).to eq 3
|
36
36
|
end
|
37
37
|
|
38
38
|
it "doesn't scale unless minimum is met" do
|
39
39
|
system = TestSystem.new(2)
|
40
|
-
strategy = cut.new(10, 4, 0.5)
|
40
|
+
strategy = cut.new(max_workers: 10, worker_capacity: 4, min_factor: 0.5)
|
41
41
|
expect(strategy.call(system, 1)).to eq 0
|
42
42
|
end
|
43
43
|
|
44
44
|
it "scales proprotionally with a minimum" do
|
45
45
|
system = TestSystem.new(3)
|
46
|
-
strategy = cut.new(10, 4, 0.5)
|
46
|
+
strategy = cut.new(max_workers: 10, worker_capacity: 4, min_factor: 0.5)
|
47
47
|
expect(strategy.call(system, 1)).to eq 1
|
48
48
|
end
|
49
49
|
|
50
50
|
it "scales maximally with a minimum" do
|
51
51
|
system = TestSystem.new(25)
|
52
|
-
strategy = cut.new(5, 4, 0.5)
|
52
|
+
strategy = cut.new(max_workers: 5, worker_capacity: 4, min_factor: 0.5)
|
53
53
|
expect(strategy.call(system, 1)).to eq 5
|
54
54
|
end
|
55
55
|
|
56
56
|
it "scales proportionally with a minimum > 1" do
|
57
57
|
system = TestSystem.new(12)
|
58
|
-
strategy = cut.new(5, 4, 2)
|
58
|
+
strategy = cut.new(max_workers: 5, worker_capacity: 4, min_factor: 2)
|
59
59
|
expect(strategy.call(system, 1)).to eq 2
|
60
60
|
end
|
61
61
|
|
62
62
|
it "scales maximally with a minimum factor > 1" do
|
63
63
|
system = TestSystem.new(30)
|
64
|
-
strategy = cut.new(5, 4, 2)
|
64
|
+
strategy = cut.new(max_workers: 5, worker_capacity: 4, min_factor: 2)
|
65
65
|
expect(strategy.call(system, 1)).to eq 5
|
66
66
|
end
|
67
67
|
|
68
68
|
it "doesn't scale down engaged workers" do
|
69
69
|
system = TestSystem.new(0, 2)
|
70
|
-
strategy = cut.new(5, 4)
|
70
|
+
strategy = cut.new(max_workers: 5, worker_capacity: 4)
|
71
71
|
expect(strategy.call(system, 1)).to eq 2
|
72
72
|
end
|
73
73
|
|
74
74
|
it "doesn't scale above max workers even if engaged workers is greater" do
|
75
75
|
system = TestSystem.new(40, 6)
|
76
|
-
strategy = cut.new(5, 4)
|
76
|
+
strategy = cut.new(max_workers: 5, worker_capacity: 4)
|
77
77
|
expect(strategy.call(system, 1)).to eq 5
|
78
78
|
end
|
79
79
|
|
80
80
|
it "returns zero if requested capacity is zero" do
|
81
81
|
system = TestSystem.new(0, 0)
|
82
|
-
strategy = cut.new(0, 0)
|
82
|
+
strategy = cut.new(max_workers: 0, worker_capacity: 0)
|
83
83
|
expect(strategy.call(system, 5)).to eq 0
|
84
84
|
end
|
85
85
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -5,8 +5,7 @@ REDIS = Sidekiq::RedisConnection.create(:url => 'redis://localhost:9736')
|
|
5
5
|
RSpec.configure do |config|
|
6
6
|
config.mock_with :rspec
|
7
7
|
|
8
|
-
config.filter_run_excluding :
|
9
|
-
config.filter_run_excluding :platform_api => true unless ENV['AUTOSCALER_HEROKU_ACCESS_TOKEN'] || ENV['HEROKU_ACCESS_TOKEN']
|
8
|
+
config.filter_run_excluding :platform_api => true unless ENV['AUTOSCALER_HEROKU_ACCESS_TOKEN']
|
10
9
|
end
|
11
10
|
|
12
11
|
class TestScaler
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: autoscaler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Love
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2018-05-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sidekiq
|
@@ -25,20 +25,6 @@ dependencies:
|
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '5.0'
|
28
|
-
- !ruby/object:Gem::Dependency
|
29
|
-
name: heroku-api
|
30
|
-
requirement: !ruby/object:Gem::Requirement
|
31
|
-
requirements:
|
32
|
-
- - "~>"
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version: '0.0'
|
35
|
-
type: :runtime
|
36
|
-
prerelease: false
|
37
|
-
version_requirements: !ruby/object:Gem::Requirement
|
38
|
-
requirements:
|
39
|
-
- - "~>"
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
version: '0.0'
|
42
28
|
- !ruby/object:Gem::Dependency
|
43
29
|
name: platform-api
|
44
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,7 +128,6 @@ files:
|
|
142
128
|
- lib/autoscaler/counter_cache_redis.rb
|
143
129
|
- lib/autoscaler/delayed_shutdown.rb
|
144
130
|
- lib/autoscaler/heroku_platform_scaler.rb
|
145
|
-
- lib/autoscaler/heroku_scaler.rb
|
146
131
|
- lib/autoscaler/ignore_scheduled_and_retrying.rb
|
147
132
|
- lib/autoscaler/linear_scaling_strategy.rb
|
148
133
|
- lib/autoscaler/sidekiq.rb
|
@@ -160,7 +145,6 @@ files:
|
|
160
145
|
- spec/autoscaler/counter_cache_redis_spec.rb
|
161
146
|
- spec/autoscaler/delayed_shutdown_spec.rb
|
162
147
|
- spec/autoscaler/heroku_platform_scaler_spec.rb
|
163
|
-
- spec/autoscaler/heroku_scaler_spec.rb
|
164
148
|
- spec/autoscaler/ignore_scheduled_and_retrying_spec.rb
|
165
149
|
- spec/autoscaler/linear_scaling_strategy_spec.rb
|
166
150
|
- spec/autoscaler/sidekiq/activity_spec.rb
|
@@ -181,9 +165,9 @@ require_paths:
|
|
181
165
|
- lib
|
182
166
|
required_ruby_version: !ruby/object:Gem::Requirement
|
183
167
|
requirements:
|
184
|
-
- - "
|
168
|
+
- - "~>"
|
185
169
|
- !ruby/object:Gem::Version
|
186
|
-
version: '
|
170
|
+
version: '2.1'
|
187
171
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
172
|
requirements:
|
189
173
|
- - ">="
|
@@ -197,20 +181,19 @@ specification_version: 4
|
|
197
181
|
summary: Start/stop Sidekiq workers on Heroku
|
198
182
|
test_files:
|
199
183
|
- Guardfile
|
200
|
-
- spec/
|
201
|
-
- spec/
|
184
|
+
- spec/spec_helper.rb
|
185
|
+
- spec/test_system.rb
|
202
186
|
- spec/autoscaler/counter_cache_redis_spec.rb
|
203
|
-
- spec/autoscaler/delayed_shutdown_spec.rb
|
204
|
-
- spec/autoscaler/heroku_platform_scaler_spec.rb
|
205
|
-
- spec/autoscaler/heroku_scaler_spec.rb
|
206
187
|
- spec/autoscaler/ignore_scheduled_and_retrying_spec.rb
|
207
188
|
- spec/autoscaler/linear_scaling_strategy_spec.rb
|
208
|
-
- spec/autoscaler/sidekiq/activity_spec.rb
|
209
189
|
- spec/autoscaler/sidekiq/client_spec.rb
|
210
|
-
- spec/autoscaler/sidekiq/entire_queue_system_spec.rb
|
211
190
|
- spec/autoscaler/sidekiq/sleep_wait_server_spec.rb
|
212
|
-
- spec/autoscaler/sidekiq/specified_queue_system_spec.rb
|
213
191
|
- spec/autoscaler/sidekiq/thread_server_spec.rb
|
214
|
-
- spec/
|
215
|
-
- spec/
|
192
|
+
- spec/autoscaler/sidekiq/specified_queue_system_spec.rb
|
193
|
+
- spec/autoscaler/sidekiq/activity_spec.rb
|
194
|
+
- spec/autoscaler/sidekiq/entire_queue_system_spec.rb
|
195
|
+
- spec/autoscaler/counter_cache_memory_spec.rb
|
196
|
+
- spec/autoscaler/binary_scaling_strategy_spec.rb
|
197
|
+
- spec/autoscaler/delayed_shutdown_spec.rb
|
198
|
+
- spec/autoscaler/heroku_platform_scaler_spec.rb
|
216
199
|
has_rdoc:
|
@@ -1,85 +0,0 @@
|
|
1
|
-
require 'heroku-api'
|
2
|
-
require 'autoscaler/counter_cache_memory'
|
3
|
-
|
4
|
-
module Autoscaler
|
5
|
-
# Wraps the Heroku API to provide just the interface that we need for scaling.
|
6
|
-
# OBSOLETE: The v1 Heroku API is no longer available, and HerokuScaler will likely be removed in a future major release. Please see current setup instructions and examples for HerokuPlatformScaler.
|
7
|
-
class HerokuScaler
|
8
|
-
# @param [String] type process type this scaler controls
|
9
|
-
# @param [String] key Heroku API key
|
10
|
-
# @param [String] app Heroku app name
|
11
|
-
def initialize(
|
12
|
-
type = 'worker',
|
13
|
-
key = ENV['HEROKU_API_KEY'],
|
14
|
-
app = ENV['HEROKU_APP'])
|
15
|
-
|
16
|
-
warn "Autoscaler: The v1 Heroku API is no longer available, and HerokuScaler will likely be removed in a future major release. Please see current setup instructions and examples for HerokuPlatformScaler."
|
17
|
-
|
18
|
-
@client = Heroku::API.new(:api_key => key)
|
19
|
-
@type = type
|
20
|
-
@app = app
|
21
|
-
@workers = CounterCacheMemory.new
|
22
|
-
end
|
23
|
-
|
24
|
-
attr_reader :app
|
25
|
-
attr_reader :type
|
26
|
-
|
27
|
-
# Read the current worker count (value may be cached)
|
28
|
-
# @return [Numeric] number of workers
|
29
|
-
def workers
|
30
|
-
@workers.counter {@workers.counter = heroku_get_workers}
|
31
|
-
end
|
32
|
-
|
33
|
-
# Set the number of workers (noop if workers the same)
|
34
|
-
# @param [Numeric] n number of workers
|
35
|
-
def workers=(n)
|
36
|
-
unknown = false
|
37
|
-
current = @workers.counter{unknown = true; 1}
|
38
|
-
if n != current || unknown
|
39
|
-
p "Scaling #{type} to #{n}"
|
40
|
-
heroku_set_workers(n)
|
41
|
-
@workers.counter = n
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Callable object which responds to exceptions during api calls #
|
46
|
-
# @example
|
47
|
-
# heroku.exception_handler = lambda {|exception| MyApp.logger.error(exception)}
|
48
|
-
# heroku.exception_handler = lambda {|exception| raise}
|
49
|
-
# # default
|
50
|
-
# lambda {|exception|
|
51
|
-
# p exception
|
52
|
-
# puts exception.backtrace
|
53
|
-
# }
|
54
|
-
attr_writer :exception_handler
|
55
|
-
|
56
|
-
# Object which supports #counter and #counter=
|
57
|
-
# Defaults to CounterCacheMemory
|
58
|
-
def counter_cache=(cache)
|
59
|
-
@workers = cache
|
60
|
-
end
|
61
|
-
|
62
|
-
private
|
63
|
-
attr_reader :client
|
64
|
-
|
65
|
-
def heroku_get_workers
|
66
|
-
client.get_ps(app).body.count {|ps| ps['process'].match /#{type}\.\d?/ }
|
67
|
-
rescue Excon::Errors::Error, Heroku::API::Errors::Error => e
|
68
|
-
exception_handler.call(e)
|
69
|
-
0
|
70
|
-
end
|
71
|
-
|
72
|
-
def heroku_set_workers(n)
|
73
|
-
client.post_ps_scale(app, type, n)
|
74
|
-
rescue Excon::Errors::Error, Heroku::API::Errors::Error => e
|
75
|
-
exception_handler.call(e)
|
76
|
-
end
|
77
|
-
|
78
|
-
def exception_handler
|
79
|
-
@exception_handler ||= lambda {|exception|
|
80
|
-
p exception
|
81
|
-
puts exception.backtrace
|
82
|
-
}
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'autoscaler/heroku_scaler'
|
3
|
-
require 'heroku/api/errors'
|
4
|
-
|
5
|
-
describe Autoscaler::HerokuScaler, :api1 => true do
|
6
|
-
let(:cut) {Autoscaler::HerokuScaler}
|
7
|
-
let(:client) {cut.new}
|
8
|
-
subject {client}
|
9
|
-
|
10
|
-
its(:workers) {should eq(0)}
|
11
|
-
|
12
|
-
describe 'scaled' do
|
13
|
-
around do |example|
|
14
|
-
client.workers = 1
|
15
|
-
example.call
|
16
|
-
client.workers = 0
|
17
|
-
end
|
18
|
-
|
19
|
-
its(:workers) {should eq(1)}
|
20
|
-
end
|
21
|
-
|
22
|
-
shared_examples 'exception handler' do |exception_class|
|
23
|
-
before do
|
24
|
-
expect(client).to receive(:client){
|
25
|
-
raise exception_class.new(Exception.new('oops'))
|
26
|
-
}
|
27
|
-
end
|
28
|
-
|
29
|
-
describe "default handler" do
|
30
|
-
it {expect{client.workers}.to_not raise_error}
|
31
|
-
it {expect(client.workers).to eq(0)}
|
32
|
-
it {expect{client.workers = 2}.to_not raise_error}
|
33
|
-
end
|
34
|
-
|
35
|
-
describe "custom handler" do
|
36
|
-
before do
|
37
|
-
@caught = false
|
38
|
-
client.exception_handler = lambda {|exception| @caught = true}
|
39
|
-
end
|
40
|
-
|
41
|
-
it {client.workers; expect(@caught).to be(true)}
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe 'exception handling', :focus => true do
|
46
|
-
it_behaves_like 'exception handler', Excon::Errors::SocketError
|
47
|
-
it_behaves_like 'exception handler', Heroku::API::Errors::Error
|
48
|
-
end
|
49
|
-
end
|