autoscaler 0.8.0 → 0.9.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +14 -2
- data/Guardfile +9 -10
- data/lib/autoscaler/counter_cache_redis.rb +9 -3
- data/lib/autoscaler/ignore_scheduled_and_retrying.rb +13 -0
- data/lib/autoscaler/linear_scaling_strategy.rb +14 -9
- data/lib/autoscaler/sidekiq/activity.rb +14 -3
- data/lib/autoscaler/sidekiq/client.rb +1 -1
- data/lib/autoscaler/sidekiq/entire_queue_system.rb +2 -6
- data/lib/autoscaler/sidekiq/monitor_middleware_adapter.rb +1 -1
- data/lib/autoscaler/sidekiq/sleep_wait_server.rb +13 -14
- data/lib/autoscaler/sidekiq/specified_queue_system.rb +4 -5
- data/lib/autoscaler/version.rb +1 -1
- data/spec/autoscaler/counter_cache_redis_spec.rb +9 -0
- data/spec/autoscaler/ignore_scheduled_and_retrying_spec.rb +33 -0
- data/spec/autoscaler/linear_scaling_strategy_spec.rb +42 -0
- data/spec/autoscaler/sidekiq/activity_spec.rb +13 -0
- data/spec/autoscaler/sidekiq/client_spec.rb +5 -0
- data/spec/autoscaler/sidekiq/monitor_middleware_adapter_spec.rb +1 -0
- data/spec/autoscaler/sidekiq/sleep_wait_server_spec.rb +18 -4
- data/spec/test_system.rb +3 -2
- metadata +33 -38
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c1870d13f3e44b1d9b2267f41fb8f5d94c94c6ec
|
4
|
+
data.tar.gz: 0a7662b031e66c6d9967567cb7612791fe6914ff
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 10566a1b1762379530e22dbfe1174212c7c23dc4078787fffdb9956d80d3dc33a4d1aba2c9298b1408579fbda1e336e05a9b1eb63124d6bfb48fd8b90de0cc94
|
7
|
+
data.tar.gz: 37fd250217015d0aabf1e99cc7773aacdbf51e6ed57bfbda0a18fe998369459b69fcbcf1126fa467ba1906539e4d20b12134ec944c17c2071849e61c5243f0ff
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,21 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.9.0
|
4
|
+
|
5
|
+
- CounterCacheRedis.new now takes a third parameter `worker_type`, a string used in the
|
6
|
+
Redis cache key. Allows for caching counts for various types of workers, not just `worker`
|
7
|
+
- Support for Sidekiq 3.0
|
8
|
+
- Strategy wrapper to ignore scheduled and retrying queues. Usage:
|
9
|
+
``new_strategy = IgnoreScheduledAndRetrying.new(my_old_strategy)``
|
10
|
+
- LinearScalingStrategy now accepts a minimum amount of work (as a percentage of worker capacity)
|
11
|
+
required to begin scaling up. E.g LinearScalingStrategy.new(10, 4, 0.5) will scale to one worker
|
12
|
+
after 4*0.5 = 2 jobs are enqueued, and a maximum of 10 workers at 10*4 jobs. Old behavior is preserved
|
13
|
+
with a default value of 0.
|
14
|
+
|
3
15
|
## 0.8.0
|
4
16
|
|
5
|
-
- Extracted caching of Heroku worker counts and added experimental Redis cache
|
6
|
-
scaler.counter_cache = Autoscaler::CounterCacheRedis(Sidekiq.method(:redis))
|
17
|
+
- Extracted caching of Heroku worker counts and added experimental Redis cache:
|
18
|
+
``scaler.counter_cache = Autoscaler::CounterCacheRedis.new(Sidekiq.method(:redis))``
|
7
19
|
- Now rescues Heroku::Api::Errors in addition to Excon::Errors
|
8
20
|
|
9
21
|
## 0.7.0
|
data/Guardfile
CHANGED
@@ -2,14 +2,13 @@ guard 'process', :name => 'redis', :command => 'redis-server spec/redis_test.con
|
|
2
2
|
watch('spec/redis_test.conf')
|
3
3
|
end
|
4
4
|
|
5
|
-
tag
|
6
|
-
example = "
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
watch(%r{^lib/(.+).rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
14
|
-
watch('spec/spec_helper.rb') { "spec" }
|
5
|
+
tag = "--tag #{ENV['TAG']}" if ENV['TAG']
|
6
|
+
example = "--example '#{ENV['EXAMPLE']}'" if ENV['EXAMPLE']
|
7
|
+
%w(sidekiq-2 sidekiq-3).each do |appraisal|
|
8
|
+
guard :rspec, :cmd => "appraisal #{appraisal} rspec --color --format d #{tag} #{example}" do
|
9
|
+
watch(%r{^spec/.+_spec\.rb$})
|
10
|
+
watch(%r{^lib/(.+).rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
11
|
+
watch('spec/spec_helper.rb') { "spec" }
|
12
|
+
end
|
15
13
|
end
|
14
|
+
|
@@ -7,14 +7,16 @@ module Autoscaler
|
|
7
7
|
# ConnectionPool: e.g. what you pass to Sidekiq.redis=
|
8
8
|
# Redis client: e.g. Redis.connect
|
9
9
|
# @param [Numeric] timeout number of seconds to allow before expiration
|
10
|
-
|
10
|
+
# @param [String] worker_type the name of the worker type, for cache keys
|
11
|
+
def initialize(redis, timeout = 5 * 60, worker_type = 'worker')
|
11
12
|
@redis = redis
|
12
13
|
@timeout = timeout
|
14
|
+
@worker_type = worker_type
|
13
15
|
end
|
14
16
|
|
15
17
|
# @param [Numeric] value new counter value
|
16
18
|
def counter=(value)
|
17
|
-
redis {|c| c.setex(
|
19
|
+
redis {|c| c.setex(key, @timeout, value)}
|
18
20
|
end
|
19
21
|
|
20
22
|
# Raised when no block is provided to #counter
|
@@ -22,7 +24,7 @@ module Autoscaler
|
|
22
24
|
|
23
25
|
# Current value. Uses the Hash#fetch api - pass a block to use in place of expired values or it will raise an exception.
|
24
26
|
def counter
|
25
|
-
value = redis {|c| c.get(
|
27
|
+
value = redis {|c| c.get(key)}
|
26
28
|
return value.to_i if value
|
27
29
|
return yield if block_given?
|
28
30
|
raise Expired
|
@@ -31,6 +33,10 @@ module Autoscaler
|
|
31
33
|
private
|
32
34
|
attr_reader :timeout
|
33
35
|
|
36
|
+
def key
|
37
|
+
['autoscaler', 'workers', @worker_type] * ':'
|
38
|
+
end
|
39
|
+
|
34
40
|
def redis(&block)
|
35
41
|
if @redis.respond_to?(:call)
|
36
42
|
@redis.call(&block)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Autoscaler
|
2
|
+
class IgnoreScheduledAndRetrying
|
3
|
+
def initialize(strategy)
|
4
|
+
@strategy = strategy
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(system, event_idle_time)
|
8
|
+
system.define_singleton_method(:scheduled) { 0 }
|
9
|
+
system.define_singleton_method(:retrying) { 0 }
|
10
|
+
@strategy.call(system, event_idle_time)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -2,24 +2,29 @@ module Autoscaler
|
|
2
2
|
# Strategies determine the target number of workers
|
3
3
|
# This strategy sets the number of workers to be proportional to the number of enqueued jobs.
|
4
4
|
class LinearScalingStrategy
|
5
|
-
#@param [integer]
|
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
|
-
|
8
|
-
|
9
|
-
@
|
7
|
+
#@param [float] min_factor minimum work required to scale, as percentage of worker_capacity
|
8
|
+
def initialize(max_workers = 1, worker_capacity = 25, min_factor = 0)
|
9
|
+
@max_workers = max_workers # max # of workers we can scale to
|
10
|
+
@total_capacity = (@max_workers * worker_capacity).to_f # total capacity of max workers
|
11
|
+
min_capacity = [0, min_factor].max.to_f * worker_capacity # min capacity required to scale first worker
|
12
|
+
@min_capacity_percentage = min_capacity / @total_capacity # min percentage of total capacity
|
10
13
|
end
|
11
14
|
|
12
15
|
# @param [QueueSystem] system interface to the queuing system
|
13
16
|
# @param [Numeric] event_idle_time number of seconds since a job related event
|
14
17
|
# @return [Integer] target number of workers
|
15
18
|
def call(system, event_idle_time)
|
16
|
-
|
17
|
-
percent_capacity = total_work(system) / total_capacity
|
19
|
+
requested_capacity_percentage = total_work(system) / @total_capacity
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
+
# Scale requested capacity taking into account the minimum required
|
22
|
+
scale_factor = (requested_capacity_percentage - @min_capacity_percentage) / (@total_capacity - @min_capacity_percentage)
|
23
|
+
scaled_capacity_percentage = scale_factor * @total_capacity
|
21
24
|
|
22
|
-
|
25
|
+
ideal_workers = ([0, scaled_capacity_percentage].max * @max_workers).ceil
|
26
|
+
|
27
|
+
return [ideal_workers, @max_workers].min
|
23
28
|
end
|
24
29
|
|
25
30
|
private
|
@@ -5,8 +5,9 @@ module Autoscaler
|
|
5
5
|
# Tracks activity timeouts using Sidekiq's redis connection
|
6
6
|
class Activity
|
7
7
|
# @param [Numeric] timeout number of seconds to wait before shutdown
|
8
|
-
def initialize(timeout)
|
8
|
+
def initialize(timeout, redis = ::Sidekiq.method(:redis))
|
9
9
|
@timeout = timeout
|
10
|
+
@redis = redis
|
10
11
|
end
|
11
12
|
|
12
13
|
# Record that a queue has activity
|
@@ -38,13 +39,23 @@ module Autoscaler
|
|
38
39
|
end
|
39
40
|
|
40
41
|
def last_activity(queues)
|
41
|
-
|
42
|
+
redis {|c|
|
42
43
|
queues.map {|q| c.get('background_activity:'+q)}.compact.max
|
43
44
|
}
|
44
45
|
end
|
45
46
|
|
46
47
|
def active_at(queue, time)
|
47
|
-
|
48
|
+
redis {|c| c.set('background_activity:'+queue, time)}
|
49
|
+
end
|
50
|
+
|
51
|
+
def redis(&block)
|
52
|
+
if @redis.respond_to?(:call)
|
53
|
+
@redis.call(&block)
|
54
|
+
elsif @redis.respond_to?(:with)
|
55
|
+
@redis.with(&block)
|
56
|
+
else
|
57
|
+
block.call(@redis)
|
58
|
+
end
|
48
59
|
end
|
49
60
|
end
|
50
61
|
end
|
@@ -17,12 +17,12 @@ module Autoscaler
|
|
17
17
|
|
18
18
|
# @return [Integer] amount of work scheduled for some time in the future
|
19
19
|
def scheduled
|
20
|
-
|
20
|
+
::Sidekiq::ScheduledSet.new.size
|
21
21
|
end
|
22
22
|
|
23
23
|
# @return [Integer] amount of work still being retried
|
24
24
|
def retrying
|
25
|
-
|
25
|
+
::Sidekiq::RetrySet.new.size
|
26
26
|
end
|
27
27
|
|
28
28
|
# @return [Array[String]]
|
@@ -35,10 +35,6 @@ module Autoscaler
|
|
35
35
|
def sidekiq_queues
|
36
36
|
::Sidekiq::Stats.new.queues
|
37
37
|
end
|
38
|
-
|
39
|
-
def count_sorted_set(sorted_set)
|
40
|
-
::Sidekiq::SortedSet.new(sorted_set).count
|
41
|
-
end
|
42
38
|
end
|
43
39
|
end
|
44
40
|
end
|
@@ -10,42 +10,41 @@ module Autoscaler
|
|
10
10
|
# @param [Numeric] timeout number of seconds to wait before shutdown
|
11
11
|
# @param [Array[String]] specified_queues list of queues to monitor to determine if there is work left. Defaults to all sidekiq queues.
|
12
12
|
def initialize(scaler, timeout, specified_queues = nil)
|
13
|
-
@scaler
|
14
|
-
@
|
15
|
-
@system
|
13
|
+
@scaler = scaler
|
14
|
+
@timeout = timeout
|
15
|
+
@system = QueueSystem.new(specified_queues)
|
16
16
|
end
|
17
17
|
|
18
18
|
# Sidekiq middleware api entry point
|
19
|
-
def call(worker, msg, queue)
|
20
|
-
working!(queue)
|
19
|
+
def call(worker, msg, queue, redis = ::Sidekiq.method(:redis))
|
20
|
+
working!(queue, redis)
|
21
21
|
yield
|
22
22
|
ensure
|
23
|
-
working!(queue)
|
24
|
-
wait_for_task_or_scale
|
23
|
+
working!(queue, redis)
|
24
|
+
wait_for_task_or_scale(redis)
|
25
25
|
end
|
26
26
|
|
27
27
|
private
|
28
|
-
def wait_for_task_or_scale
|
28
|
+
def wait_for_task_or_scale(redis)
|
29
29
|
loop do
|
30
30
|
return if pending_work?
|
31
|
-
return @scaler.workers = 0 if idle?
|
31
|
+
return @scaler.workers = 0 if idle?(redis)
|
32
32
|
sleep(0.5)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
attr_reader :system
|
37
|
-
attr_reader :activity
|
38
37
|
|
39
38
|
def pending_work?
|
40
39
|
system.queued > 0 || system.scheduled > 0 || system.retrying > 0
|
41
40
|
end
|
42
41
|
|
43
|
-
def working!(queue)
|
44
|
-
|
42
|
+
def working!(queue, redis)
|
43
|
+
Activity.new(@timeout, redis).working!(queue)
|
45
44
|
end
|
46
45
|
|
47
|
-
def idle?
|
48
|
-
|
46
|
+
def idle?(redis)
|
47
|
+
Activity.new(@timeout, redis).idle?(system.queue_names)
|
49
48
|
end
|
50
49
|
end
|
51
50
|
end
|
@@ -24,12 +24,12 @@ module Autoscaler
|
|
24
24
|
|
25
25
|
# @return [Integer] amount of work scheduled for some time in the future
|
26
26
|
def scheduled
|
27
|
-
|
27
|
+
count_set(::Sidekiq::ScheduledSet.new)
|
28
28
|
end
|
29
29
|
|
30
30
|
# @return [Integer] amount of work still being retried
|
31
31
|
def retrying
|
32
|
-
|
32
|
+
count_set(::Sidekiq::RetrySet.new)
|
33
33
|
end
|
34
34
|
|
35
35
|
# @return [Array[String]]
|
@@ -40,9 +40,8 @@ module Autoscaler
|
|
40
40
|
::Sidekiq::Stats.new.queues
|
41
41
|
end
|
42
42
|
|
43
|
-
def
|
44
|
-
|
45
|
-
ss.count { |job| queue_names.include?(job.queue) }
|
43
|
+
def count_set(set)
|
44
|
+
set.count { |job| queue_names.include?(job.queue) }
|
46
45
|
end
|
47
46
|
end
|
48
47
|
end
|
data/lib/autoscaler/version.rb
CHANGED
@@ -18,6 +18,15 @@ describe Autoscaler::CounterCacheRedis do
|
|
18
18
|
subject.counter.should == 2
|
19
19
|
end
|
20
20
|
|
21
|
+
it 'does not conflict with multiple worker types' do
|
22
|
+
other_worker_cache = cut.new(@redis, 300, 'other_worker')
|
23
|
+
subject.counter = 1
|
24
|
+
other_worker_cache.counter = 2
|
25
|
+
|
26
|
+
subject.counter.should == 1
|
27
|
+
other_worker_cache.counter = 2
|
28
|
+
end
|
29
|
+
|
21
30
|
it 'times out' do
|
22
31
|
cache = cut.new(Sidekiq.method(:redis), 1) # timeout 0 invalid
|
23
32
|
cache.counter = 3
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'test_system'
|
3
|
+
require 'autoscaler/ignore_scheduled_and_retrying'
|
4
|
+
|
5
|
+
describe Autoscaler::IgnoreScheduledAndRetrying do
|
6
|
+
let(:cut) {Autoscaler::IgnoreScheduledAndRetrying}
|
7
|
+
|
8
|
+
it "passes through enqueued" do
|
9
|
+
system = Struct.new(:enqueued).new(3)
|
10
|
+
strategy = proc {|system, time| system.enqueued}
|
11
|
+
cut.new(strategy).call(system, 0).should == 3
|
12
|
+
end
|
13
|
+
|
14
|
+
it "passes through workers" do
|
15
|
+
system = Struct.new(:workers).new(3)
|
16
|
+
strategy = proc {|system, time| system.workers}
|
17
|
+
cut.new(strategy).call(system, 0).should == 3
|
18
|
+
end
|
19
|
+
|
20
|
+
it "ignores scheduled" do
|
21
|
+
system = Struct.new(:scheduled).new(3)
|
22
|
+
strategy = proc {|system, time| system.scheduled}
|
23
|
+
cut.new(strategy).call(system, 0).should == 0
|
24
|
+
end
|
25
|
+
|
26
|
+
it "ignores retrying" do
|
27
|
+
system = Struct.new(:retrying).new(3)
|
28
|
+
strategy = proc {|system, time| system.retrying}
|
29
|
+
cut.new(strategy).call(system, 0).should == 0
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
@@ -34,4 +34,46 @@ describe Autoscaler::LinearScalingStrategy do
|
|
34
34
|
strategy = cut.new(5, 2)
|
35
35
|
strategy.call(system, 1).should == 3
|
36
36
|
end
|
37
|
+
|
38
|
+
it "doesn't scale unless minimum is met" do
|
39
|
+
system = TestSystem.new(2)
|
40
|
+
strategy = cut.new(10, 4, 0.5)
|
41
|
+
strategy.call(system, 1).should == 0
|
42
|
+
end
|
43
|
+
|
44
|
+
it "scales proprotionally with a minimum" do
|
45
|
+
system = TestSystem.new(3)
|
46
|
+
strategy = cut.new(10, 4, 0.5)
|
47
|
+
strategy.call(system, 1).should == 1
|
48
|
+
end
|
49
|
+
|
50
|
+
it "scales maximally with a minimum" do
|
51
|
+
system = TestSystem.new(25)
|
52
|
+
strategy = cut.new(5, 4, 0.5)
|
53
|
+
strategy.call(system, 1).should == 5
|
54
|
+
end
|
55
|
+
|
56
|
+
it "scales proportionally with a minimum > 1" do
|
57
|
+
system = TestSystem.new(12)
|
58
|
+
strategy = cut.new(5, 4, 2)
|
59
|
+
strategy.call(system, 1).should == 2
|
60
|
+
end
|
61
|
+
|
62
|
+
it "scales maximally with a minimum factor > 1" do
|
63
|
+
system = TestSystem.new(30)
|
64
|
+
strategy = cut.new(5, 4, 2)
|
65
|
+
strategy.call(system, 1).should == 5
|
66
|
+
end
|
67
|
+
|
68
|
+
xit "doesn't scale down engaged workers" do
|
69
|
+
system = TestSystem.new(0, 2)
|
70
|
+
strategy = cut.new(5, 4)
|
71
|
+
strategy.call(system, 1).should == 2
|
72
|
+
end
|
73
|
+
|
74
|
+
xit "doesn't scale above max workers even if engaged workers is greater" do
|
75
|
+
system = TestSystem.new(40, 6)
|
76
|
+
strategy = cut.new(5, 4)
|
77
|
+
strategy.call(system, 1).should == 5
|
78
|
+
end
|
37
79
|
end
|
@@ -18,4 +18,17 @@ describe Autoscaler::Sidekiq::Activity do
|
|
18
18
|
end
|
19
19
|
it {activity.should be_idle(['queue'])}
|
20
20
|
end
|
21
|
+
|
22
|
+
it 'passed a connection pool' do
|
23
|
+
activity = cut.new(5, @redis)
|
24
|
+
activity.working!('queue')
|
25
|
+
activity.should_not be_idle(['queue'])
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'passed a plain connection' do
|
29
|
+
connection = Redis.connect(:url => 'http://localhost:9736', :namespace => 'autoscaler')
|
30
|
+
activity = cut.new(5, connection)
|
31
|
+
activity.working!('queue')
|
32
|
+
activity.should_not be_idle(['queue'])
|
33
|
+
end
|
21
34
|
end
|
@@ -13,6 +13,11 @@ describe Autoscaler::Sidekiq::Client do
|
|
13
13
|
scaler.workers.should == 1
|
14
14
|
end
|
15
15
|
|
16
|
+
it 'scales with a redis pool' do
|
17
|
+
client.call(Class, {}, 'queue', ::Sidekiq.method(:redis)) {}
|
18
|
+
scaler.workers.should == 1
|
19
|
+
end
|
20
|
+
|
16
21
|
it('yields') {client.call(Class, {}, 'queue') {:foo}.should == :foo}
|
17
22
|
end
|
18
23
|
|
@@ -12,4 +12,5 @@ describe Autoscaler::Sidekiq::MonitorMiddlewareAdapter do
|
|
12
12
|
let(:server) {cut.new(scaler, 0, ['queue'])}
|
13
13
|
|
14
14
|
it('yields') {server.call(Object.new, {}, 'queue') {:foo}.should == :foo}
|
15
|
+
it('yields with a redis pool') {server.call(Object.new, {}, 'queue', Sidekiq.method(:redis)) {:foo}.should == :foo}
|
15
16
|
end
|
@@ -11,10 +11,7 @@ describe Autoscaler::Sidekiq::SleepWaitServer do
|
|
11
11
|
let(:scaler) {TestScaler.new(1)}
|
12
12
|
let(:server) {cut.new(scaler, 0, ['queue'])}
|
13
13
|
|
14
|
-
|
15
|
-
server.call(Object.new, {}, 'queue') {}
|
16
|
-
end
|
17
|
-
|
14
|
+
shared_examples "a sleepwait server" do
|
18
15
|
it "scales with no work" do
|
19
16
|
server.stub(:pending_work?).and_return(false)
|
20
17
|
when_run
|
@@ -26,6 +23,23 @@ describe Autoscaler::Sidekiq::SleepWaitServer do
|
|
26
23
|
when_run
|
27
24
|
scaler.workers.should == 1
|
28
25
|
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "a middleware with no redis specified" do
|
29
|
+
it_behaves_like "a sleepwait server" do
|
30
|
+
def when_run
|
31
|
+
server.call(Object.new, {}, 'queue') {}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "a middleware with redis specified" do
|
37
|
+
it_behaves_like "a sleepwait server" do
|
38
|
+
def when_run
|
39
|
+
server.call(Object.new, {}, 'queue', Sidekiq.method(:redis)) {}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
29
43
|
|
30
44
|
it('yields') {server.call(Object.new, {}, 'queue') {:foo}.should == :foo}
|
31
45
|
end
|
data/spec/test_system.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
class TestSystem
|
2
|
-
def initialize(pending)
|
2
|
+
def initialize(pending, current = 0)
|
3
3
|
@pending = pending
|
4
|
+
@current = current
|
4
5
|
end
|
5
6
|
|
6
|
-
def workers;
|
7
|
+
def workers; @current; end
|
7
8
|
def queued; @pending; end
|
8
9
|
def scheduled; 0; end
|
9
10
|
def retrying; 0; end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: autoscaler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.9.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Justin Love
|
@@ -10,102 +9,96 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date: 2014-
|
12
|
+
date: 2014-05-19 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: sidekiq
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
|
-
- -
|
18
|
+
- - ">="
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: '2.7'
|
21
|
+
- - "<"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '3.1'
|
23
24
|
type: :runtime
|
24
25
|
prerelease: false
|
25
26
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
27
|
requirements:
|
28
|
-
- -
|
28
|
+
- - ">="
|
29
29
|
- !ruby/object:Gem::Version
|
30
30
|
version: '2.7'
|
31
|
+
- - "<"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.1'
|
31
34
|
- !ruby/object:Gem::Dependency
|
32
35
|
name: heroku-api
|
33
36
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
37
|
requirements:
|
36
|
-
- -
|
38
|
+
- - ">="
|
37
39
|
- !ruby/object:Gem::Version
|
38
40
|
version: '0'
|
39
41
|
type: :runtime
|
40
42
|
prerelease: false
|
41
43
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
44
|
requirements:
|
44
|
-
- -
|
45
|
+
- - ">="
|
45
46
|
- !ruby/object:Gem::Version
|
46
47
|
version: '0'
|
47
48
|
- !ruby/object:Gem::Dependency
|
48
49
|
name: bundler
|
49
50
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
57
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
58
|
requirements:
|
60
|
-
- -
|
59
|
+
- - ">="
|
61
60
|
- !ruby/object:Gem::Version
|
62
61
|
version: '0'
|
63
62
|
- !ruby/object:Gem::Dependency
|
64
63
|
name: rspec
|
65
64
|
requirement: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
65
|
requirements:
|
68
|
-
- -
|
66
|
+
- - ">="
|
69
67
|
- !ruby/object:Gem::Version
|
70
68
|
version: '0'
|
71
69
|
type: :development
|
72
70
|
prerelease: false
|
73
71
|
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
72
|
requirements:
|
76
|
-
- -
|
73
|
+
- - ">="
|
77
74
|
- !ruby/object:Gem::Version
|
78
75
|
version: '0'
|
79
76
|
- !ruby/object:Gem::Dependency
|
80
77
|
name: guard-rspec
|
81
78
|
requirement: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
79
|
requirements:
|
84
|
-
- -
|
80
|
+
- - ">="
|
85
81
|
- !ruby/object:Gem::Version
|
86
82
|
version: '0'
|
87
83
|
type: :development
|
88
84
|
prerelease: false
|
89
85
|
version_requirements: !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
91
86
|
requirements:
|
92
|
-
- -
|
87
|
+
- - ">="
|
93
88
|
- !ruby/object:Gem::Version
|
94
89
|
version: '0'
|
95
90
|
- !ruby/object:Gem::Dependency
|
96
91
|
name: guard-process
|
97
92
|
requirement: !ruby/object:Gem::Requirement
|
98
|
-
none: false
|
99
93
|
requirements:
|
100
|
-
- -
|
94
|
+
- - ">="
|
101
95
|
- !ruby/object:Gem::Version
|
102
96
|
version: '0'
|
103
97
|
type: :development
|
104
98
|
prerelease: false
|
105
99
|
version_requirements: !ruby/object:Gem::Requirement
|
106
|
-
none: false
|
107
100
|
requirements:
|
108
|
-
- -
|
101
|
+
- - ">="
|
109
102
|
- !ruby/object:Gem::Version
|
110
103
|
version: '0'
|
111
104
|
description: Currently provides a Sidekiq middleware that does 0/1 scaling of Heroku
|
@@ -117,13 +110,19 @@ extensions: []
|
|
117
110
|
extra_rdoc_files: []
|
118
111
|
files:
|
119
112
|
- CHANGELOG.md
|
113
|
+
- Guardfile
|
120
114
|
- README.md
|
115
|
+
- examples/complex.rb
|
116
|
+
- examples/simple.rb
|
117
|
+
- lib/autoscaler.rb
|
121
118
|
- lib/autoscaler/binary_scaling_strategy.rb
|
122
119
|
- lib/autoscaler/counter_cache_memory.rb
|
123
120
|
- lib/autoscaler/counter_cache_redis.rb
|
124
121
|
- lib/autoscaler/delayed_shutdown.rb
|
125
122
|
- lib/autoscaler/heroku_scaler.rb
|
123
|
+
- lib/autoscaler/ignore_scheduled_and_retrying.rb
|
126
124
|
- lib/autoscaler/linear_scaling_strategy.rb
|
125
|
+
- lib/autoscaler/sidekiq.rb
|
127
126
|
- lib/autoscaler/sidekiq/activity.rb
|
128
127
|
- lib/autoscaler/sidekiq/celluloid_monitor.rb
|
129
128
|
- lib/autoscaler/sidekiq/client.rb
|
@@ -132,18 +131,14 @@ files:
|
|
132
131
|
- lib/autoscaler/sidekiq/queue_system.rb
|
133
132
|
- lib/autoscaler/sidekiq/sleep_wait_server.rb
|
134
133
|
- lib/autoscaler/sidekiq/specified_queue_system.rb
|
135
|
-
- lib/autoscaler/sidekiq.rb
|
136
134
|
- lib/autoscaler/stub_scaler.rb
|
137
135
|
- lib/autoscaler/version.rb
|
138
|
-
- lib/autoscaler.rb
|
139
|
-
- examples/complex.rb
|
140
|
-
- examples/simple.rb
|
141
|
-
- Guardfile
|
142
136
|
- spec/autoscaler/binary_scaling_strategy_spec.rb
|
143
137
|
- spec/autoscaler/counter_cache_memory_spec.rb
|
144
138
|
- spec/autoscaler/counter_cache_redis_spec.rb
|
145
139
|
- spec/autoscaler/delayed_shutdown_spec.rb
|
146
140
|
- spec/autoscaler/heroku_scaler_spec.rb
|
141
|
+
- spec/autoscaler/ignore_scheduled_and_retrying_spec.rb
|
147
142
|
- spec/autoscaler/linear_scaling_strategy_spec.rb
|
148
143
|
- spec/autoscaler/sidekiq/activity_spec.rb
|
149
144
|
- spec/autoscaler/sidekiq/celluloid_monitor_spec.rb
|
@@ -156,27 +151,26 @@ files:
|
|
156
151
|
- spec/test_system.rb
|
157
152
|
homepage: ''
|
158
153
|
licenses: []
|
154
|
+
metadata: {}
|
159
155
|
post_install_message:
|
160
156
|
rdoc_options: []
|
161
157
|
require_paths:
|
162
158
|
- lib
|
163
159
|
required_ruby_version: !ruby/object:Gem::Requirement
|
164
|
-
none: false
|
165
160
|
requirements:
|
166
|
-
- -
|
161
|
+
- - ">="
|
167
162
|
- !ruby/object:Gem::Version
|
168
163
|
version: '0'
|
169
164
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
170
|
-
none: false
|
171
165
|
requirements:
|
172
|
-
- -
|
166
|
+
- - ">="
|
173
167
|
- !ruby/object:Gem::Version
|
174
168
|
version: '0'
|
175
169
|
requirements: []
|
176
170
|
rubyforge_project: autoscaler
|
177
|
-
rubygems_version:
|
171
|
+
rubygems_version: 2.2.0
|
178
172
|
signing_key:
|
179
|
-
specification_version:
|
173
|
+
specification_version: 4
|
180
174
|
summary: Start/stop Sidekiq workers on Heroku
|
181
175
|
test_files:
|
182
176
|
- Guardfile
|
@@ -185,6 +179,7 @@ test_files:
|
|
185
179
|
- spec/autoscaler/counter_cache_redis_spec.rb
|
186
180
|
- spec/autoscaler/delayed_shutdown_spec.rb
|
187
181
|
- spec/autoscaler/heroku_scaler_spec.rb
|
182
|
+
- spec/autoscaler/ignore_scheduled_and_retrying_spec.rb
|
188
183
|
- spec/autoscaler/linear_scaling_strategy_spec.rb
|
189
184
|
- spec/autoscaler/sidekiq/activity_spec.rb
|
190
185
|
- spec/autoscaler/sidekiq/celluloid_monitor_spec.rb
|