rcarvalho-workless 1.0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 lostboy
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,100 @@
1
+ [![Build Status](https://secure.travis-ci.org/lostboy/workless.png?branch=master)](http://travis-ci.org/lostboy/workless)
2
+
3
+ # Workless
4
+
5
+ This is an addon for delayed_job (> 2.0.0) http://github.com/collectiveidea/delayed_job
6
+ It is designed to be used when you're using Heroku as a host and have the need to do background work with delayed job but you don't want to leave the workers running all the time as it costs money.
7
+
8
+ By adding the gem to your project and configuring our Heroku app with some config variables workless should do the rest.
9
+
10
+ ## Update
11
+
12
+ Version 1.0.0 has been released, this brings compatibility with delayed_job 3 and compatibility with Rails 2.3.x and up.
13
+
14
+ ## Compatibility
15
+
16
+ Workless should work correctly with Rubies 1.8.7, ree, 1.9.2 and 1.9.3. It is compatible with Delayed Job since version 2.0.7 up to the latest version 3.0.1, the table below shows tested compatibility with ruby, rails and delayed_job
17
+
18
+ Ruby | Rails | Delayed Job
19
+ ---------- | ------ | -----
20
+ 1.8.7-ree | 2.1.14 | 2.0.7
21
+ 1.9.2 | 3.2 | 2.1.4
22
+ 1.9.2 | 3.2 | 3.0.1
23
+
24
+ ## Installation
25
+
26
+ Add the workless gem and the delayed_job gem to your project Gemfile and update your bundle. Its is recommended to specify the gem version for delayed_job especially if you are using rails 2.3.x which doesn't work with the latest delayed_job
27
+
28
+ ### For rails 2.3.x the latest compatible delayed_job is 2.0.7
29
+
30
+ <pre>
31
+ gem "delayed_job", "2.0.7"
32
+ gem "workless", "~> 1.0.1"
33
+ </pre>
34
+
35
+ ### For rails 3.x with delayed_job 2.1.x
36
+
37
+ <pre>
38
+ gem "delayed_job", "~> 2.1.4"
39
+ gem "workless", "~> 1.0.1"
40
+ </pre>
41
+
42
+ ### For rails 3.x with latest delayed_job 3.x using active record
43
+
44
+ <pre>
45
+ gem "delayed_job_active_record"
46
+ gem "workless", "~> 1.0.1"
47
+ </pre>
48
+
49
+ If you don't specify delayed_job in your Gemfile workless will bring it in, most likly the latest version (3.0.1)
50
+
51
+ Add your Heroku username / password as config vars to your Heroku instance, the same one you log in to Heroku with.
52
+ [You may also use your API key as the password](https://github.com/heroku/heroku/issues/103).
53
+
54
+ <pre>
55
+ heroku config:add HEROKU_USER=yourusername HEROKU_PASSWORD=yourpassword
56
+ </pre>
57
+
58
+ And for cedar apps add the app name
59
+
60
+ <pre>
61
+ heroku config:add APP_NAME=yourherokuappname
62
+ </pre>
63
+
64
+ ## Failing Jobs
65
+
66
+ In the case of failed jobs Workless will only shut down the dj worker if all attempts have been tried. By default Delayed Job will try 25 times to process a job with ever increasing time delays between each unsucessful attempt. Because of this Workless configures Delayed Job to try failed jobs only 3 times to reduce the amount of time a worker can be running while trying to process them.
67
+
68
+ ## Configuration
69
+
70
+ Workless can be disabled by using the null scaler that will ignore the workers requests to scale up and down. In an environment file add this in the config block:
71
+
72
+ <pre>
73
+ config.after_initialize do
74
+ Delayed::Job.scaler = :null
75
+ end
76
+ </pre>
77
+
78
+ There are three other scalers included. Note that if you are running on the Aspen or Bamboo stacks on Heroku and you don't explicitly specify the scaler, the heroku scaler will be used automatically.
79
+
80
+ <pre>
81
+ Delayed::Job.scaler = :heroku
82
+ Delayed::Job.scaler = :heroku_cedar
83
+ Delayed::Job.scaler = :local
84
+ </pre>
85
+
86
+ The local scaler uses @adamwiggins rush library http://github.com/adamwiggins/rush to start and stop workers on a local machine
87
+
88
+ The heroku scaler works on the Aspen and Bamboo stacks while the heroku_cedar scaler only works on the new Cedar stack.
89
+
90
+ ## Note on Patches/Pull Requests
91
+
92
+ * Please fork the project, as you can see there are no tests and at present I don't know how to go about adding them so any advice would be welcome.
93
+ * Make your feature addition or bug fix.
94
+ * Commit, do not mess with rakefile, version, or history.
95
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
96
+ * Send me a pull request.
97
+
98
+ ## Copyright
99
+
100
+ Copyright (c) 2010 lostboy. See LICENSE for details.
data/lib/workless.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "heroku"
2
+ require File.dirname(__FILE__) + "/workless/scalers/base"
3
+ require File.dirname(__FILE__) + "/workless/scaler"
4
+ require File.dirname(__FILE__) + "/workless/railtie" if defined?(Rails::Railtie)
@@ -0,0 +1,3 @@
1
+ Delayed::Worker.max_attempts = 3
2
+ Delayed::Backend::ActiveRecord::Job.send(:include, Delayed::Workless::Scaler) if defined?(Delayed::Backend::ActiveRecord::Job)
3
+ Delayed::Backend::Mongoid::Job.send(:include, Delayed::Workless::Scaler) if defined?(Delayed::Backend::Mongoid::Job)
@@ -0,0 +1,10 @@
1
+ require 'rails'
2
+ require 'delayed_job'
3
+
4
+ module Delayed
5
+ class Railtie < Rails::Railtie
6
+ initializer :after_initialize do
7
+ require 'workless/initialize'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ require 'workless/scalers/heroku'
2
+ require 'workless/scalers/heroku_cedar'
3
+ require 'workless/scalers/local'
4
+ require 'workless/scalers/null'
5
+
6
+ module Delayed
7
+ module Workless
8
+ module Scaler
9
+
10
+ def self.included(base)
11
+ base.send :extend, ClassMethods
12
+ base.class_eval do
13
+ after_destroy "self.class.scaler.down"
14
+ before_create "self.class.scaler.up"
15
+ after_update "self.class.scaler.down", :unless => Proc.new {|r| r.failed_at.nil? }
16
+ end
17
+
18
+ end
19
+
20
+ module ClassMethods
21
+ def scaler
22
+ @scaler ||= if ENV.include?("HEROKU_USER")
23
+ client = ::Heroku::Client.new(ENV['HEROKU_USER'], ENV['HEROKU_PASSWORD'])
24
+ case client.info(ENV["APP_NAME"])[:stack]
25
+ when "cedar"
26
+ Scaler::HerokuCedar
27
+ else
28
+ Scaler::Heroku
29
+ end
30
+ else
31
+ Scaler::Local
32
+ end
33
+ end
34
+
35
+ def scaler=(scaler)
36
+ @scaler = "Delayed::Workless::Scaler::#{scaler.to_s.camelize}".constantize
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,39 @@
1
+ require 'delayed_job'
2
+
3
+ module Delayed
4
+ module Workless
5
+ module Scaler
6
+
7
+ class Base
8
+ def self.jobs
9
+ Delayed::Job.all(:conditions => { :failed_at => nil })
10
+ end
11
+
12
+ def self.calculate_num_workers
13
+ num_workers = self.workers
14
+ if num_workers.class == Fixnum
15
+ job_count = self.jobs.count
16
+ if job_count > 500
17
+ return 4 unless num_workers > 3
18
+ elsif job_count > 200
19
+ return 3 unless num_workers > 2
20
+ elsif job_count > 50
21
+ return 2 unless num_workers > 1
22
+ elsif job_count > 0
23
+ return 1 unless num_workers > 0
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ module HerokuClient
30
+
31
+ def client
32
+ @client ||= ::Heroku::Client.new(ENV['HEROKU_USER'], ENV['HEROKU_PASSWORD'])
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,28 @@
1
+ require 'heroku'
2
+
3
+ module Delayed
4
+ module Workless
5
+ module Scaler
6
+
7
+ class Heroku < Base
8
+
9
+ extend Delayed::Workless::Scaler::HerokuClient
10
+
11
+ def self.up
12
+ nw = self.calculate_num_workers
13
+ client.set_workers(ENV['APP_NAME'], nw) if nw
14
+ end
15
+
16
+ def self.down
17
+ client.set_workers(ENV['APP_NAME'], 0) unless self.workers == 0 or self.jobs.count > 0
18
+ end
19
+
20
+ def self.workers
21
+ client.info(ENV['APP_NAME'])[:workers].to_i
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ require 'heroku'
2
+
3
+ module Delayed
4
+ module Workless
5
+ module Scaler
6
+
7
+ class HerokuCedar < Base
8
+
9
+ extend Delayed::Workless::Scaler::HerokuClient
10
+
11
+ def self.up
12
+ nw = self.calculate_num_workers
13
+ client.ps_scale(ENV['APP_NAME'], :type => 'worker', :qty => nw) if nw
14
+ end
15
+
16
+ def self.down
17
+ client.ps_scale(ENV['APP_NAME'], :type => 'worker', :qty => 0) unless self.workers == 0 or self.jobs.count > 0
18
+ end
19
+
20
+ def self.workers
21
+ client.ps(ENV['APP_NAME']).count { |p| p["process"] =~ /worker\.\d?/ }
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ require 'rush'
2
+
3
+ module Delayed
4
+ module Workless
5
+ module Scaler
6
+
7
+ class Local < Base
8
+
9
+ def self.up
10
+ if self.workers == 0
11
+ Rush::Box.new[Rails.root].bash("script/delayed_job start -i workless", :background => true)
12
+ sleep 1
13
+ end
14
+ true
15
+ end
16
+
17
+ def self.down
18
+ unless jobs.count > 0 and workers > 0
19
+ Rush::Box.new[Rails.root].bash("script/delayed_job stop -i workless", :background => true)
20
+ end
21
+ true
22
+ end
23
+
24
+ def self.workers
25
+ Rush::Box.new.processes.filter(:cmdline => /delayed_job start -i workless|delayed_job.workless/).size
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ module Delayed
2
+ module Workless
3
+ module Scaler
4
+
5
+ class Null < Base
6
+
7
+ def self.up
8
+ end
9
+
10
+ def self.down
11
+ end
12
+
13
+ end
14
+
15
+ end
16
+ end
17
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + "/../lib/workless/initialize"
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rcarvalho-workless
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - lostboy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-06-30 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: &2156064120 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2156064120
25
+ - !ruby/object:Gem::Dependency
26
+ name: heroku
27
+ requirement: &2156063120 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2156063120
36
+ - !ruby/object:Gem::Dependency
37
+ name: rush
38
+ requirement: &2156062120 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *2156062120
47
+ - !ruby/object:Gem::Dependency
48
+ name: delayed_job
49
+ requirement: &2156061140 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 2.0.7
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *2156061140
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec
60
+ requirement: &2156060360 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *2156060360
69
+ description: Extension to Delayed Job to enable workers to scale up when needed
70
+ email: paul.crabtree@gmail.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - rails/init.rb
76
+ - lib/workless/initialize.rb
77
+ - lib/workless/railtie.rb
78
+ - lib/workless/scaler.rb
79
+ - lib/workless/scalers/base.rb
80
+ - lib/workless/scalers/heroku.rb
81
+ - lib/workless/scalers/heroku_cedar.rb
82
+ - lib/workless/scalers/local.rb
83
+ - lib/workless/scalers/null.rb
84
+ - lib/workless.rb
85
+ - LICENSE
86
+ - README.md
87
+ homepage: http://github.com/lostboy/workless
88
+ licenses: []
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: 1.3.6
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 1.8.6
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: Use delayed job workers only when theyre needed on Heroku
111
+ test_files: []