heroku_resque_autoscaler 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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in heroku_resque_autoscaler.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 G5
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.
data/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # Heroku Resque Autoscaler
2
+
3
+ Uses Resque Job Hooks and the Heroku API gem to autoscale Heroku Resque workers
4
+
5
+ Inspired by [@darkhelmet](https://github.com/darkhelmet)'s
6
+ [Auto-scale Your Resque Workers On Heroku](http://verboselogging.com/2010/07/30/auto-scale-your-resque-workers-on-heroku)
7
+
8
+
9
+ ## Current Version
10
+
11
+ 0.0.1
12
+
13
+
14
+ ## Requirements
15
+
16
+ * ["heroku_api", "~> 0.3.5"](http://rubygems.org/gems/heroku-api)
17
+ * ["resque", "~> 1.23.0"](http://rubygems.org/gems/resque)
18
+
19
+
20
+ ## Installation
21
+
22
+ ### Gemfile
23
+
24
+ Add this line to your application's Gemfile:
25
+
26
+ ```ruby
27
+ gem 'heroku_resque_autoscaler'
28
+ ```
29
+
30
+ ### Manual
31
+
32
+ Or install it yourself:
33
+
34
+ ```bash
35
+ gem install heroku_resque_autoscaler
36
+ ```
37
+
38
+
39
+ ## Usage
40
+
41
+ Set defaults in an initializer, defaults are shown:
42
+
43
+ ```ruby
44
+ HerokuResqueAutoscaler.configure do |config|
45
+ config.heroku_api_key = ENV["HEROKU_API_KEY"]
46
+ config.heroku_app_name = ENV["HEROKU_APP_NAME"]
47
+ end
48
+ ```
49
+
50
+ Export you environment variables wherever you do that:
51
+
52
+ ```bash
53
+ export HEROKU_API_KEY=heroku_api_key
54
+ export HEROKU_APP_NAME=heroku_app_name
55
+ ```
56
+
57
+ Your Resque workers should extend HerokuResqueAutoscaler:
58
+
59
+ ```ruby
60
+ class AutoscaledJob
61
+ extend HerokuResqueAutoscaler
62
+
63
+ def self.perform
64
+ # Do something
65
+ end
66
+ end
67
+ ```
68
+
69
+
70
+ ## Authors
71
+
72
+ * Jessica Lynn Suttles / [@jlsuttles](https://github.com/jlsuttles)
73
+ * Bookis Smuin / [@bookis](https://github.com/bookis)
74
+
75
+
76
+ ## Contributing
77
+
78
+ 1. Fork it
79
+ 2. Get it running
80
+ 3. Create your feature branch (`git checkout -b my-new-feature`)
81
+ 4. Write your code and **specs**
82
+ 5. Commit your changes (`git commit -am 'Add some feature'`)
83
+ 6. Push to the branch (`git push origin my-new-feature`)
84
+ 7. Create new Pull Request
85
+
86
+ If you find bugs, have feature requests or questions, please
87
+ [file an issue](https://github.com/G5/heroku_resque_autoscaler/issues).
88
+
89
+
90
+ ## Specs
91
+
92
+ ```bash
93
+ rspec spec
94
+ ```
95
+
96
+
97
+ ## License
98
+
99
+ Copyright (c) 2012 G5
100
+
101
+ MIT License
102
+
103
+ Permission is hereby granted, free of charge, to any person obtaining
104
+ a copy of this software and associated documentation files (the
105
+ "Software"), to deal in the Software without restriction, including
106
+ without limitation the rights to use, copy, modify, merge, publish,
107
+ distribute, sublicense, and/or sell copies of the Software, and to
108
+ permit persons to whom the Software is furnished to do so, subject to
109
+ the following conditions:
110
+
111
+ The above copyright notice and this permission notice shall be
112
+ included in all copies or substantial portions of the Software.
113
+
114
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
115
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
116
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
117
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
118
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
119
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
120
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/heroku_resque_autoscaler/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "heroku_resque_autoscaler"
6
+ gem.version = HerokuResqueAutoscaler::VERSION
7
+ gem.authors = ["Jessica Lynn Suttles"]
8
+ gem.email = ["jlsuttles@gmail.com"]
9
+ gem.description = %q{Uses Resque Job Hooks and the Heroku API gem to autoscale Heroku Resque workers}
10
+ gem.summary = %q{Uses Resque Job Hooks and the Heroku API gem to autoscale Heroku Resque workers}
11
+ gem.homepage = ""
12
+
13
+ gem.files = `git ls-files`.split($\)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.require_paths = ["lib"]
17
+
18
+ gem.add_runtime_dependency "heroku-api", "~> 0.3.5"
19
+ gem.add_runtime_dependency "resque", "~> 1.23.0"
20
+
21
+ gem.add_development_dependency "rspec", "~> 2.11.0"
22
+ gem.add_development_dependency "guard-rspec", "~> 2.1.0"
23
+ gem.add_development_dependency "rb-fsevent", "~> 0.9.2"
24
+ gem.add_development_dependency "debugger", "~> 1.2.1"
25
+ end
@@ -0,0 +1,52 @@
1
+ module HerokuResqueAutoscaler
2
+ class Configuration
3
+ OPTIONS = {
4
+ heroku_api_key: ENV["HEROKU_API_KEY"],
5
+ heroku_app_name: ENV["HEROKU_APP_NAME"],
6
+ }
7
+
8
+ # Defines accessors for all OPTIONS
9
+ OPTIONS.each_pair do |key, value|
10
+ attr_accessor key
11
+ end
12
+
13
+ # Initializes defaults to be the environment varibales of the same names
14
+ def initialize
15
+ OPTIONS.each_pair do |key, value|
16
+ self.send("#{key}=", value)
17
+ end
18
+ end
19
+
20
+ # Allows config options to be read like a hash
21
+ #
22
+ # @param [Symbol] option Key for a given attribute
23
+ def [](option)
24
+ send(option)
25
+ end
26
+
27
+ # Returns a hash of all configurable options
28
+ def to_hash
29
+ OPTIONS.inject({}) do |hash, option|
30
+ key = option.first
31
+ hash[key] = self.send(key)
32
+ hash
33
+ end
34
+ end
35
+
36
+ # Returns a hash of all configurable options merged with +hash+
37
+ #
38
+ # @param [Hash] hash A set of configuration options that will take
39
+ # precedence over the defaults
40
+ def merge(hash)
41
+ to_hash.merge(hash)
42
+ end
43
+
44
+ def validate_presence(options)
45
+ OPTIONS.each_pair do |key, value|
46
+ if options[key].nil?
47
+ raise HerokuResqueAutoscaler::ConfigurationException, "#{key} is missing"
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module GithubHerokuDeployer
2
+ class ConfigurationException < StandardError; end
3
+ end
@@ -0,0 +1,78 @@
1
+ require "heroku-api"
2
+ require "resque"
3
+
4
+ module HerokuResqueAutoscaler
5
+ module Scaler
6
+ class << self
7
+ # TODO: use HerokuResqueAutoscaler.configuration for api_key
8
+ @@heroku = Heroku::API.new(api_key: ENV["HEROKU_API_KEY"])
9
+
10
+ def api_key
11
+ HerokuResqueAutoscaler.configuration["heroku_api_key"]
12
+ end
13
+
14
+ def app_name
15
+ HerokuResqueAutoscaler.configuration["heroku_app_name"]
16
+ end
17
+
18
+ def workers
19
+ @@heroku.get_ps(app_name).body.keep_if do |ps|
20
+ ps["process"] =~ /worker/
21
+ end.length.to_i
22
+ end
23
+
24
+ def workers=(qty)
25
+ @@heroku.post_ps_scale(app_name, :worker, qty)
26
+ end
27
+
28
+ def job_count
29
+ Resque.info[:pending].to_i
30
+ end
31
+
32
+ def working_job_count
33
+ Resque.info[:working].to_i
34
+ end
35
+ end
36
+ end
37
+
38
+ def after_perform_scale_down(*args)
39
+ # Scale everything down if we have no pending jobs and one working job (this one)
40
+ Scaler.workers = 0 if Scaler.job_count.zero? && Scaler.working_job_count == 1
41
+ end
42
+
43
+ def num_desired_heroku_workers(*args)
44
+ [
45
+ {
46
+ :workers => 1, # This many workers
47
+ :job_count => 1 # For this many jobs or more, until the next level
48
+ },
49
+ {
50
+ :workers => 2,
51
+ :job_count => 15
52
+ },
53
+ {
54
+ :workers => 3,
55
+ :job_count => 25
56
+ },
57
+ {
58
+ :workers => 4,
59
+ :job_count => 40
60
+ },
61
+ {
62
+ :workers => 5,
63
+ :job_count => 60
64
+ }
65
+ ].reverse_each do |scale_info|
66
+ if Scaler.job_count >= scale_info[:job_count]
67
+ return scale_info[:workers]
68
+ end
69
+ end
70
+ end
71
+
72
+ def after_enqueue_scale_up(*args)
73
+ desired_workers = num_desired_heroku_workers
74
+ if Scaler.workers < desired_workers
75
+ Scaler.workers = desired_workers
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,3 @@
1
+ module HerokuResqueAutoscaler
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,31 @@
1
+ require "heroku_resque_autoscaler/version"
2
+ require "heroku_resque_autoscaler/configuration"
3
+ require "heroku_resque_autoscaler/scaler"
4
+
5
+ module HerokuResqueAutoscaler
6
+ class << self
7
+ # A HerokuResqueAutoscaler configuration object. Must act like a hash and
8
+ # return sensible values for all HerokuResqueAutoscaler configuration options.
9
+ #
10
+ # @see HerokuResqueAutoscaler::Configuration.
11
+ attr_writer :configuration
12
+
13
+ # The configuration object.
14
+ #
15
+ # @see HerokuResqueAutoscaler.configure
16
+ def configuration
17
+ @configuration ||= Configuration.new
18
+ end
19
+
20
+ # Call this method to modify defaults in your initializers.
21
+ #
22
+ # @example
23
+ # HerokuResqueAutoscaler.configure do |config|
24
+ # config.heroku_api_key = ENV["HEROKU_API_KEY"]
25
+ # config.heroku_app_name = ENV["HEROKU_APP_NAME"]
26
+ # end
27
+ def configure
28
+ yield(configuration)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'heroku_resque_autoscaler'
3
+ require 'heroku_resque_autoscaler/configuration'
4
+
5
+ describe HerokuResqueAutoscaler::Configuration do
6
+ it { should respond_to :"[]" }
7
+ it { should respond_to :to_hash }
8
+ it { should respond_to :merge }
9
+
10
+ it "provides default values" do
11
+ assert_config_default :heroku_api_key, ENV["HEROKU_API_KEY"]
12
+ end
13
+
14
+ it "allows values to be overwritten" do
15
+ assert_config_overridable :heroku_api_key
16
+ end
17
+
18
+ it "acts like a hash" do
19
+ config = HerokuResqueAutoscaler::Configuration.new
20
+ hash = config.to_hash
21
+ HerokuResqueAutoscaler::Configuration::OPTIONS.each_pair do |key, value|
22
+ config[key].should eq(hash[key])
23
+ end
24
+ end
25
+
26
+ it "is mergable" do
27
+ config = HerokuResqueAutoscaler::Configuration.new
28
+ hash = config.to_hash
29
+ config.merge(:key => 'value').should eq(hash.merge(:key => 'value'))
30
+ end
31
+
32
+ def assert_config_default(option, default_value, config = nil)
33
+ config ||= HerokuResqueAutoscaler::Configuration.new
34
+ config.send(option).should eq(default_value)
35
+ end
36
+
37
+ def assert_config_overridable(option, value = 'a value')
38
+ config = HerokuResqueAutoscaler::Configuration.new
39
+ config.send(:"#{option}=", value)
40
+ config.send(option).should eq(value)
41
+ end
42
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+ require 'heroku_resque_autoscaler'
3
+ require 'heroku_resque_autoscaler/scaler'
4
+
5
+ require "spec_helper"
6
+
7
+ class HerokuResqueAutoscalerTestClass
8
+ extend HerokuResqueAutoscaler
9
+ end
10
+
11
+ describe HerokuResqueAutoscaler do
12
+ before :each do
13
+ @heroku = mock(Heroku::API)
14
+ HerokuResqueAutoscaler::Scaler.class_variable_set(:@@heroku, @heroku)
15
+ end
16
+
17
+ let(:heroku_app) {ENV['HEROKU_APP_NAME']}
18
+
19
+ context "#workers" do
20
+ it "returns the number of workers from the Heroku application" do
21
+ @heroku.should_receive(:get_ps).with(heroku_app).and_return([
22
+ {"process" => "web.1"},
23
+ {"process" => "worker.1"},
24
+ {"process" => "worker.1"},
25
+ ])
26
+ HerokuResqueAutoscaler::Scaler.workers.should == 2
27
+ end
28
+ end
29
+
30
+ context "#workers=" do
31
+ it "sets the number of workers on Heroku to some quantity" do
32
+ quantity = 10
33
+ @heroku.should_receive(:post_ps_scale).with(heroku_app, :worker, quantity)
34
+ HerokuResqueAutoscaler::Scaler.workers = quantity
35
+ end
36
+ end
37
+
38
+ context "#job_count" do
39
+ it "returns the Resque job count" do
40
+ num_pending = 10
41
+ Resque.should_receive(:info).and_return({:pending => num_pending})
42
+ HerokuResqueAutoscaler::Scaler.job_count.should == num_pending
43
+ end
44
+ end
45
+
46
+ context "#num_desired_heroku_workers" do
47
+ it "returns the number of workers we should have (1 worker per x jobs)" do
48
+ num_jobs = 100
49
+ HerokuResqueAutoscaler::Scaler.stub(:job_count).and_return(num_jobs)
50
+ HerokuResqueAutoscalerTestClass.num_desired_heroku_workers.should == 5
51
+
52
+ num_jobs = 38
53
+ HerokuResqueAutoscaler::Scaler.unstub(:job_count)
54
+ HerokuResqueAutoscaler::Scaler.stub(:job_count).and_return(num_jobs)
55
+ HerokuResqueAutoscalerTestClass.num_desired_heroku_workers.should == 3
56
+
57
+ num_jobs = 1
58
+ HerokuResqueAutoscaler::Scaler.unstub(:job_count)
59
+ HerokuResqueAutoscaler::Scaler.stub(:job_count).and_return(num_jobs)
60
+ HerokuResqueAutoscalerTestClass.num_desired_heroku_workers.should == 1
61
+
62
+ num_jobs = 10000
63
+ HerokuResqueAutoscaler::Scaler.unstub(:job_count)
64
+ HerokuResqueAutoscaler::Scaler.stub(:job_count).and_return(num_jobs)
65
+ HerokuResqueAutoscalerTestClass.num_desired_heroku_workers.should == 5
66
+ end
67
+ end
68
+
69
+ context "#after_perform_scale_down" do
70
+ it "scales down the workers to zero if there are no jobs pending" do
71
+ HerokuResqueAutoscaler::Scaler.stub(:job_count).and_return(0)
72
+ HerokuResqueAutoscaler::Scaler.stub(:workers).and_return(1)
73
+ HerokuResqueAutoscaler::Scaler.stub(:working_job_count).and_return(1)
74
+ HerokuResqueAutoscaler::Scaler.should_receive(:workers=).with(0)
75
+ HerokuResqueAutoscalerTestClass.after_perform_scale_down
76
+ end
77
+
78
+ it "does not scale down the workers if there are jobs pending" do
79
+ HerokuResqueAutoscaler::Scaler.stub(:job_count).and_return(1)
80
+ HerokuResqueAutoscaler::Scaler.should_not_receive(:workers=)
81
+ HerokuResqueAutoscalerTestClass.after_perform_scale_down
82
+ end
83
+ end
84
+
85
+ context "#after_enqueue_scale_up" do
86
+ it "ups the amount of workers if there are not enough" do
87
+ num_workers = 5
88
+ num_desired_workers = 6
89
+ HerokuResqueAutoscaler::Scaler.stub(:workers).and_return(num_workers)
90
+ HerokuResqueAutoscalerTestClass.stub(:num_desired_heroku_workers).and_return(num_desired_workers)
91
+ HerokuResqueAutoscaler::Scaler.should_receive(:workers=).with(num_desired_workers)
92
+ HerokuResqueAutoscalerTestClass.after_enqueue_scale_up
93
+ end
94
+
95
+ it "does not change the amount of workers if there more workers than needed" do
96
+ num_workers = 6
97
+ num_desired_workers = 5
98
+ HerokuResqueAutoscaler::Scaler.stub(:workers).and_return(num_workers)
99
+ HerokuResqueAutoscalerTestClass.stub(:num_desired_heroku_workers).and_return(num_desired_workers)
100
+ HerokuResqueAutoscaler::Scaler.should_not_receive(:workers=)
101
+ HerokuResqueAutoscalerTestClass.after_enqueue_scale_up
102
+ end
103
+
104
+ it "does not change the amount of workers if there are exactly the number required" do
105
+ num_workers = 6
106
+ num_desired_workers = 6
107
+ HerokuResqueAutoscaler::Scaler.stub(:workers).and_return(num_workers)
108
+ HerokuResqueAutoscalerTestClass.stub(:num_desired_heroku_workers).and_return(num_desired_workers)
109
+ HerokuResqueAutoscaler::Scaler.should_not_receive(:workers=)
110
+ HerokuResqueAutoscalerTestClass.after_enqueue_scale_up
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ require 'heroku_resque_autoscaler'
3
+
4
+ describe HerokuResqueAutoscaler do
5
+ it { should respond_to :configuration }
6
+ it { should respond_to :configure }
7
+
8
+ describe "::configuration" do
9
+ it "should be the configuration object" do
10
+ HerokuResqueAutoscaler.configuration.should(
11
+ be_a_kind_of HerokuResqueAutoscaler::Configuration)
12
+ end
13
+
14
+ it "give a new instance if non defined" do
15
+ HerokuResqueAutoscaler.configuration = nil
16
+ HerokuResqueAutoscaler.configuration.should(
17
+ be_a_kind_of HerokuResqueAutoscaler::Configuration)
18
+ end
19
+ end
20
+
21
+ describe "::configure" do
22
+ it "should yield the configuration object" do
23
+ HerokuResqueAutoscaler.configure do |config|
24
+ config.should equal(HerokuResqueAutoscaler.configuration)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure do |config|
2
+ config.color = true
3
+ end
metadata ADDED
@@ -0,0 +1,167 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: heroku_resque_autoscaler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jessica Lynn Suttles
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: heroku-api
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.3.5
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.3.5
30
+ - !ruby/object:Gem::Dependency
31
+ name: resque
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 1.23.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.23.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 2.11.0
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 2.11.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: guard-rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 2.1.0
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 2.1.0
78
+ - !ruby/object:Gem::Dependency
79
+ name: rb-fsevent
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 0.9.2
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 0.9.2
94
+ - !ruby/object:Gem::Dependency
95
+ name: debugger
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 1.2.1
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 1.2.1
110
+ description: Uses Resque Job Hooks and the Heroku API gem to autoscale Heroku Resque
111
+ workers
112
+ email:
113
+ - jlsuttles@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - Gemfile
120
+ - LICENSE
121
+ - README.md
122
+ - Rakefile
123
+ - heroku_resque_autoscaler.gemspec
124
+ - lib/heroku_resque_autoscaler.rb
125
+ - lib/heroku_resque_autoscaler/configuration.rb
126
+ - lib/heroku_resque_autoscaler/exceptions.rb
127
+ - lib/heroku_resque_autoscaler/scaler.rb
128
+ - lib/heroku_resque_autoscaler/version.rb
129
+ - spec/lib/heroku_resque_autoscaler/configuration_spec.rb
130
+ - spec/lib/heroku_resque_autoscaler/scaler_spec.rb
131
+ - spec/lib/heroku_resque_autoscaler_spec.rb
132
+ - spec/spec_helper.rb
133
+ homepage: ''
134
+ licenses: []
135
+ post_install_message:
136
+ rdoc_options: []
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ! '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ segments:
146
+ - 0
147
+ hash: -4159626300690751562
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ segments:
155
+ - 0
156
+ hash: -4159626300690751562
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 1.8.24
160
+ signing_key:
161
+ specification_version: 3
162
+ summary: Uses Resque Job Hooks and the Heroku API gem to autoscale Heroku Resque workers
163
+ test_files:
164
+ - spec/lib/heroku_resque_autoscaler/configuration_spec.rb
165
+ - spec/lib/heroku_resque_autoscaler/scaler_spec.rb
166
+ - spec/lib/heroku_resque_autoscaler_spec.rb
167
+ - spec/spec_helper.rb