heroku_auto_scale 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 49c7a5cc62bb1678668a81d5eaf42a9926c68a60
4
+ data.tar.gz: 0a785b077800bf7df5a0e84a07ffe604bf286c1a
5
+ SHA512:
6
+ metadata.gz: cf0fac72297a756ef03071588309eaab6ef55240868894f3f43e1c3673bcd166bb752f1b78294dc4da16dfdf9de477fae6699a8ae53cc26d305e9600b6c7dc9e
7
+ data.tar.gz: d3e741458014a95a4d10ecd0ba11a82149e798be2a36e00a630a937a69b29634feaa5499cc33e308ceb275bb7a2ed91695479b5dcafca755f2d5086b64001b08
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format documentation
3
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in heroku_auto_scale.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 luki3k5
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,81 @@
1
+ # HerokuAutoScale
2
+
3
+ Idea of this gem is to allow for simple and queue system agnostic
4
+ scalability of background jobs on heroku.
5
+
6
+ Imagine having multimple queues of some kind, each time there are no
7
+ jobs these queues are just hanging there - wasting their time staying online.
8
+ On the other hand when there is a spike in number of scheduled jobs it would be
9
+ good to increase the number of dynos to process them faster.
10
+
11
+ This gem provides simple DSL for doing just that.
12
+ It allows to set a meaningful constrains for your dynos such as
13
+ minimum/maximum number of dynos and scaling step.
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ ```ruby
20
+ gem 'heroku_auto_scale'
21
+ ```
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install heroku_auto_scale
30
+
31
+ In case of rails applications you may want to create new initializer
32
+ with the following content:
33
+
34
+ ```ruby
35
+
36
+ include HerokuAutoScale
37
+
38
+ HerokuAutoScale.configure do |c|
39
+ c.redis_url = ENV['REDISCLOUD_URL']
40
+ c.heroku_oauth_token = ENV['HEROKU_TOKEN']
41
+ c.heroku_app_name = ENV['APP_NAME']
42
+ end
43
+
44
+
45
+ ```
46
+
47
+ Make sure that you have corresponding environment variables setup.
48
+
49
+ ## Usage
50
+
51
+ Below is simple example how to use this gem:
52
+
53
+ ```ruby
54
+
55
+ heroku_observe do
56
+ queue_name "queue:followers_jobs"
57
+ process_name "sidekiq_followers"
58
+
59
+ max_dynos 2
60
+ min_dynos 1
61
+ scaling_step 2000
62
+ end
63
+
64
+ ```
65
+
66
+ The meaning of options is:
67
+ - queue_name - the name of the queue in redis that you wish to observe
68
+ - process_name - name of the heroku process to scale
69
+ - max_dynos - maximum number of dynos you want to scale up to
70
+ - min_dynos - minimum number of dynos you want to scale down to
71
+ - scaling_step - number of jobs it take to scale your dynos
72
+
73
+ For adding timely checks I recommend using great [clockwork](https://github.com/adamwiggins/clockwork)
74
+
75
+ ## Contributing
76
+
77
+ 1. Fork it ( https://github.com/[my-github-username]/heroku_auto_scale/fork )
78
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
79
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
80
+ 4. Push to the branch (`git push origin my-new-feature`)
81
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'heroku_auto_scale/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "heroku_auto_scale"
8
+ spec.version = HerokuAutoScale::VERSION
9
+ spec.authors = ["luki3k5"]
10
+ spec.email = ["luki3k5@gmail.com"]
11
+ spec.summary = %q{Simple DSL for creating scaling rules for worker dynos on Heroku}
12
+ spec.description = %q{Simple DSL for creating scaling rules for worker dynos on Heroku}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'platform-api'
22
+ spec.add_dependency 'redis'
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.7"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.2"
27
+ spec.add_development_dependency "rspec-collection_matchers"
28
+ spec.add_development_dependency "webmock"
29
+
30
+ spec.add_development_dependency "awesome_print"
31
+ spec.add_development_dependency "pry"
32
+ end
@@ -0,0 +1,52 @@
1
+ require "heroku_auto_scale/version"
2
+ require "heroku_auto_scale/manager"
3
+ require "heroku_auto_scale/configuration"
4
+
5
+ module HerokuAutoScale
6
+ extend Configuration
7
+
8
+ class << self
9
+ def included(includer)
10
+ includer.send("include", Methods)
11
+ includer.extend(Methods)
12
+ end
13
+
14
+ def manager
15
+ @manager ||= Manager.new
16
+ end
17
+ end
18
+
19
+ module Methods
20
+
21
+ def heroku_observe
22
+ yield
23
+ manage_queue
24
+ end
25
+
26
+ def process_name(process_name)
27
+ HerokuAutoScale.manager.set_process_name(process_name)
28
+ end
29
+
30
+ def queue_name(queue_name)
31
+ HerokuAutoScale.manager.set_queue_name(queue_name)
32
+ end
33
+
34
+ def scaling_step(step)
35
+ HerokuAutoScale.manager.set_scaling_step(step)
36
+ end
37
+
38
+ def max_dynos(number_of_dynos)
39
+ HerokuAutoScale.manager.set_max_dynos(number_of_dynos)
40
+ end
41
+
42
+ def min_dynos(number_of_dynos)
43
+ HerokuAutoScale.manager.set_min_dynos(number_of_dynos)
44
+ end
45
+
46
+ def manage_queue
47
+ HerokuAutoScale.manager.manage_queue
48
+ end
49
+ end
50
+
51
+ extend Methods
52
+ end
@@ -0,0 +1,21 @@
1
+ module HerokuAutoScale
2
+ module Configuration
3
+ CONFIGURATION_OPTIONS = [
4
+ :redis_url,
5
+ :heroku_oauth_token,
6
+ :heroku_app_name
7
+ ].freeze
8
+
9
+ attr_accessor *CONFIGURATION_OPTIONS
10
+
11
+ def configure
12
+ yield self
13
+ end
14
+
15
+ def options
16
+ CONFIGURATION_OPTIONS.inject({}) do |option, key|
17
+ option.merge!(key => send(key))
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,32 @@
1
+ require 'platform-api'
2
+
3
+ module HerokuAutoScale
4
+ class HerokuOperations
5
+ attr_reader :heroku_connection, :app_name
6
+
7
+ def initialize(api_key, app_name)
8
+ @heroku_connection = PlatformAPI.connect_oauth(api_key)
9
+ @app_name = app_name
10
+ end
11
+
12
+ def execute_dyno_scale(process_name, new_number_of_dynos)
13
+ if should_scale?(process_name, new_number_of_dynos)
14
+ scale_dynos(process_name, new_number_of_dynos)
15
+ end
16
+ end
17
+
18
+ private
19
+ def scale_dynos(process_name, new_number_of_dynos)
20
+ heroku_connection.formation.update(
21
+ app_name,
22
+ process_name,
23
+ {"quantity" => new_number_of_dynos}
24
+ )
25
+ end
26
+
27
+ def should_scale?(process_name, new_number_of_dynos)
28
+ response = heroku_connection.formation.info(app_name, process_name)
29
+ response["quantity"] != new_number_of_dynos
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,81 @@
1
+ require 'heroku_auto_scale/redis_operations'
2
+ require 'heroku_auto_scale'
3
+ require 'heroku_auto_scale/configuration'
4
+ require 'heroku_auto_scale/heroku_operations'
5
+
6
+ module HerokuAutoScale
7
+ class Manager
8
+ MNGR_ATTRIBUTES = [
9
+ :process_name,
10
+ :queue_name,
11
+ :redis_operations,
12
+ :heroku_operations,
13
+ :min_dynos,
14
+ :max_dynos,
15
+ :scaling_step
16
+ ].freeze
17
+
18
+ attr_accessor *HerokuAutoScale::Configuration::CONFIGURATION_OPTIONS
19
+ attr_accessor *MNGR_ATTRIBUTES
20
+
21
+ def initialize(options={})
22
+ options = HerokuAutoScale.options.merge(options)
23
+ Configuration::CONFIGURATION_OPTIONS.each do |key|
24
+ send("#{key}=", options[key])
25
+ end
26
+
27
+ init_redis_operations
28
+ init_heroku_operations
29
+ end
30
+
31
+ def get_number_of_jobs_inside_queue
32
+ redis_operations.check_queue_for_jobs(@queue_name)
33
+ end
34
+
35
+ def set_process_name(process_name)
36
+ @process_name = process_name
37
+ end
38
+
39
+ def set_queue_name(queue_name)
40
+ @queue_name = queue_name
41
+ end
42
+
43
+ def set_min_dynos(min_dynos)
44
+ @min_dynos = min_dynos
45
+ end
46
+
47
+ def set_max_dynos(max_dynos)
48
+ @max_dynos = max_dynos
49
+ end
50
+
51
+ def set_scaling_step(scaling_step)
52
+ @scaling_step = scaling_step
53
+ end
54
+
55
+ def manage_queue
56
+ scale_to = calculate_number_of_needed_dynos
57
+ heroku_operations.execute_dyno_scale(process_name, scale_to)
58
+ end
59
+
60
+ def calculate_number_of_needed_dynos
61
+ current_jobs = get_number_of_jobs_inside_queue
62
+ dynos = (current_jobs.to_f / scaling_step.to_f).ceil
63
+
64
+ scale_to = [dynos, max_dynos].min
65
+ scale_to = [scale_to, min_dynos].max
66
+ end
67
+
68
+ private
69
+ def init_redis_operations
70
+ @redis_operations = HerokuAutoScale::RedisOperations.new(redis_url)
71
+ end
72
+
73
+ def init_heroku_operations
74
+ @heroku_operations = HerokuAutoScale::
75
+ HerokuOperations.new(
76
+ heroku_oauth_token,
77
+ heroku_app_name
78
+ )
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,26 @@
1
+ require 'redis'
2
+
3
+ module HerokuAutoScale
4
+ class RedisOperations
5
+ attr_reader :redis_connection
6
+
7
+ def initialize(url)
8
+ @redis_connection = Redis.new(url: url)
9
+ end
10
+
11
+ def check_queue_for_jobs(queue_name)
12
+ check_queue(queue_name)
13
+ redis_connection.llen(queue_name)
14
+ end
15
+
16
+ private
17
+ def check_queue(queue_name)
18
+ available_keys = redis_connection.keys
19
+ unless available_keys.include?(queue_name)
20
+ raise "There is no key #{queue_name}, \n
21
+ available keys are:\n
22
+ #{available_keys}"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module HerokuAutoScale
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe HerokuAutoScale::Configuration do
4
+ subject do
5
+ Object.new.extend(HerokuAutoScale::Configuration)
6
+ end
7
+
8
+ it 'allows to set allowed attributes' do
9
+ subject.configure do |c|
10
+ c.redis_url = 'url'
11
+ c.heroku_oauth_token = 'token'
12
+ c.heroku_app_name = 'app'
13
+ end
14
+
15
+ expect(subject.redis_url).to eq('url')
16
+ expect(subject.heroku_oauth_token).to eq('token')
17
+ expect(subject.heroku_app_name).to eq('app')
18
+ end
19
+
20
+ it 'retuns hash of it\'s attributes' do
21
+ subject.configure do |c|
22
+ c.redis_url = 'url'
23
+ c.heroku_oauth_token = 'token'
24
+ c.heroku_app_name = 'app'
25
+ end
26
+
27
+ expect(subject.options).to eq({
28
+ :redis_url=>"url",
29
+ :heroku_oauth_token=>"token",
30
+ :heroku_app_name=>"app"
31
+ })
32
+ end
33
+
34
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe HerokuAutoScale::HerokuOperations do
4
+ subject { HerokuAutoScale::HerokuOperations.new("api_key", "app_name") }
5
+
6
+ let(:heroku_info_response) do
7
+ {
8
+ "command" => "bundle exec fake_process_name",
9
+ "created_at" => "2015-04-13T11:36:03Z",
10
+ "id" => "xxx-xxx-xxx-xxx",
11
+ "type" => "sidekiq_followers",
12
+ "quantity" => 1,
13
+ "size" => "2X",
14
+ "updated_at" => "2015-05-10T17:26:08Z"
15
+ }
16
+ end
17
+
18
+ context 'should_scale?' do
19
+ it 'doesn\'t allow to scale for the same no. of dynos' do
20
+ allow(subject).to receive_message_chain(:heroku_connection, :formation, :info).
21
+ and_return(heroku_info_response)
22
+ expect(subject.send(:should_scale?, "process_name", 1)).to eq(false)
23
+ end
24
+
25
+ it 'does allow to scale for the greater no. of dynos' do
26
+ allow(subject).to receive_message_chain(:heroku_connection, :formation, :info).
27
+ and_return(heroku_info_response)
28
+ expect(subject.send(:should_scale?, "process_name", 2)).to eq(true)
29
+ end
30
+
31
+ it 'does allow to scale for the smaller no. of dynos' do
32
+ allow(subject).to receive_message_chain(:heroku_connection, :formation, :info).
33
+ and_return(heroku_info_response)
34
+ expect(subject.send(:should_scale?, "process_name", 0)).to eq(true)
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ describe HerokuAutoScale::Manager do
4
+ let(:redis_test_url_for_test) { "redis://localhost" }
5
+ let(:heroku_oauth_token_for_test) { "token" }
6
+ let(:heroku_app_name_for_test) { "app" }
7
+ let(:config_values) do
8
+ [
9
+ redis_test_url_for_test,
10
+ heroku_oauth_token_for_test,
11
+ heroku_app_name_for_test
12
+ ]
13
+ end
14
+
15
+ before do
16
+ @keys = HerokuAutoScale::Configuration::CONFIGURATION_OPTIONS
17
+ end
18
+
19
+ context 'configuration' do
20
+ before(:each) do
21
+ HerokuAutoScale.configure do |c|
22
+ c.redis_url = redis_test_url_for_test
23
+ c.heroku_oauth_token = heroku_oauth_token_for_test
24
+ c.heroku_app_name = heroku_app_name_for_test
25
+ end
26
+ end
27
+
28
+ it 'should inherit the config' do
29
+ manager = HerokuAutoScale::Manager.new
30
+ @keys.each do |key|
31
+ expect(
32
+ config_values.include?(manager.send(key))
33
+ ).to eq(true)
34
+ end
35
+ end
36
+ end
37
+
38
+ context 'accepting attributes' do
39
+ let(:manager) { HerokuAutoScale::Manager.new }
40
+
41
+ it '#set_process_name' do
42
+ manager.set_process_name("some_process_name")
43
+ expect(manager.process_name).to eq("some_process_name")
44
+ end
45
+
46
+ it '#set_queue_name' do
47
+ manager.set_queue_name("some_queue_name")
48
+ expect(manager.queue_name).to eq("some_queue_name")
49
+ end
50
+
51
+ it '#set_min_dynos' do
52
+ manager.set_min_dynos(1)
53
+ expect(manager.min_dynos).to eq(1)
54
+ end
55
+
56
+ it '#set_max_dynos' do
57
+ manager.set_max_dynos(2)
58
+ expect(manager.max_dynos).to eq(2)
59
+ end
60
+
61
+ it '#set_scaling_step' do
62
+ manager.set_scaling_step(12000)
63
+ expect(manager.scaling_step).to eq(12000)
64
+ end
65
+
66
+ end
67
+
68
+ describe 'dynos numbers for scalability' do
69
+ let(:manager) { HerokuAutoScale::Manager.new }
70
+
71
+ it 'sets 0 dynos when there are no jobs and min_dynos(0)' do
72
+ manager.set_scaling_step(10_000)
73
+ manager.set_min_dynos(0)
74
+ manager.set_max_dynos(10)
75
+ allow(manager).to receive(:get_number_of_jobs_inside_queue) { 0 }
76
+
77
+ expect(manager.calculate_number_of_needed_dynos).to eq(0)
78
+ end
79
+
80
+ it 'sets to min dynos when there are no jobs and min_dynos(1)' do
81
+ manager.set_scaling_step(10_000)
82
+ manager.set_min_dynos(1)
83
+ manager.set_max_dynos(10)
84
+ allow(manager).to receive(:get_number_of_jobs_inside_queue) { 0 }
85
+
86
+ expect(manager.calculate_number_of_needed_dynos).to eq(1)
87
+ end
88
+
89
+ it 'sets 1 dynos when there are jobs till the first scaling_step' do
90
+ manager.set_scaling_step(10_000)
91
+ manager.set_min_dynos(0)
92
+ manager.set_max_dynos(10)
93
+ allow(manager).to receive(:get_number_of_jobs_inside_queue) { 8_000 }
94
+
95
+ expect(manager.calculate_number_of_needed_dynos).to eq(1)
96
+ end
97
+
98
+ it 'sets 2 dynos when there are jobs till the second scaling_step' do
99
+ manager.set_scaling_step(10_000)
100
+ manager.set_min_dynos(0)
101
+ manager.set_max_dynos(10)
102
+ allow(manager).to receive(:get_number_of_jobs_inside_queue) { 18_000 }
103
+
104
+ expect(manager.calculate_number_of_needed_dynos).to eq(2)
105
+ end
106
+
107
+ it 'sets max allowed dynos when there are jobs that exceed max_dynos x scaling_step' do
108
+ manager.set_scaling_step(10_000)
109
+ manager.set_min_dynos(0)
110
+ manager.set_max_dynos(4)
111
+ allow(manager).to receive(:get_number_of_jobs_inside_queue) { 180_000 }
112
+
113
+ expect(manager.calculate_number_of_needed_dynos).to eq(4)
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+ require 'rspec/collection_matchers'
4
+ require 'heroku_auto_scale'
5
+ require 'webmock/rspec'
6
+
7
+ WebMock.disable_net_connect!(allow_localhost: true)
8
+
9
+ RSpec.configure do |config|
10
+ config.mock_framework = :rspec
11
+ end
metadata ADDED
@@ -0,0 +1,191 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: heroku_auto_scale
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - luki3k5
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: platform-api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: redis
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-collection_matchers
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: awesome_print
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Simple DSL for creating scaling rules for worker dynos on Heroku
140
+ email:
141
+ - luki3k5@gmail.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".gitignore"
147
+ - ".rspec"
148
+ - Gemfile
149
+ - LICENSE.txt
150
+ - README.md
151
+ - Rakefile
152
+ - heroku_auto_scale.gemspec
153
+ - lib/heroku_auto_scale.rb
154
+ - lib/heroku_auto_scale/configuration.rb
155
+ - lib/heroku_auto_scale/heroku_operations.rb
156
+ - lib/heroku_auto_scale/manager.rb
157
+ - lib/heroku_auto_scale/redis_operations.rb
158
+ - lib/heroku_auto_scale/version.rb
159
+ - spec/heroku_auto_scale/configuration_spec.rb
160
+ - spec/heroku_auto_scale/heroku_operations_spec.rb
161
+ - spec/heroku_auto_scale/manager_spec.rb
162
+ - spec/spec_helper.rb
163
+ homepage: ''
164
+ licenses:
165
+ - MIT
166
+ metadata: {}
167
+ post_install_message:
168
+ rdoc_options: []
169
+ require_paths:
170
+ - lib
171
+ required_ruby_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ required_rubygems_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ requirements: []
182
+ rubyforge_project:
183
+ rubygems_version: 2.4.3
184
+ signing_key:
185
+ specification_version: 4
186
+ summary: Simple DSL for creating scaling rules for worker dynos on Heroku
187
+ test_files:
188
+ - spec/heroku_auto_scale/configuration_spec.rb
189
+ - spec/heroku_auto_scale/heroku_operations_spec.rb
190
+ - spec/heroku_auto_scale/manager_spec.rb
191
+ - spec/spec_helper.rb