collectiveidea-delayed_job 1.8.0 → 1.8.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -11,16 +11,113 @@ It is a direct extraction from Shopify where the job table is responsible for a
11
11
  * updating solr, our search server, after product changes
12
12
  * batch imports
13
13
  * spam checks
14
-
15
- h2. Setup
16
-
14
+
15
+ h2. Installation
16
+
17
+ To install as a gem, add the following to @config/environment.rb@:
18
+
19
+ <pre>
20
+ config.gem 'collectiveidea-delayed_job', :lib => 'delayed_job',
21
+ :source => 'http://gems.github.com'
22
+ </pre>
23
+
24
+ Rake tasks are not automatically loaded from gems, so you'll need to add the following to your Rakefile:
25
+
26
+ <pre>
27
+ begin
28
+ require 'delayed/tasks'
29
+ rescue LoadError
30
+ STDERR.puts "Run `rake gems:install` to install delayed_job"
31
+ end
32
+ </pre>
33
+
34
+ To install as a plugin:
35
+
36
+ <pre>
37
+ script/plugin install git://github.com/collectiveidea/delayed_job.git
38
+ </pre>
39
+
40
+ After delayed_job is installed, run:
41
+
42
+ <pre>
43
+ script/generate delayed_job
44
+ rake db:migrate
45
+ </pre>
46
+
47
+ h2. Upgrading to 1.8
48
+
49
+ If you are upgrading from a previous release, you will need to generate the new @script/delayed_job@:
50
+
51
+ <pre>
52
+ script/generate delayed_job --skip-migration
53
+ </pre>
54
+
55
+ h2. Queuing Jobs
56
+
57
+ Call @#send_later(method, params)@ on any object and it will be processed in the background.
58
+
59
+ <pre>
60
+ # without delayed_job
61
+ Notifier.deliver_signup(@user)
62
+
63
+ # with delayed_job
64
+ Notifier.send_later :deliver_signup, @user
65
+ </pre>
66
+
67
+ If a method should always be run in the background, you can call @#handle_asynchronously@ after the method declaration:
68
+
69
+ <pre>
70
+ class Device
71
+ def deliver
72
+ # long running method
73
+ end
74
+ handle_asynchronously :deliver
75
+ end
76
+
77
+ device = Device.new
78
+ device.deliver
79
+ </pre>
80
+
81
+ h2. Running Jobs
82
+
83
+ @script/delayed_job@ can be used to manage a background process which will start working off jobs.
84
+
85
+ <pre>
86
+ $ ruby script/delayed_job -e production start
87
+ $ ruby script/delayed_job -e production stop
88
+
89
+ # Runs two workers in separate processes.
90
+ $ ruby script/delayed_job -e production -n 2 start
91
+ $ ruby script/delayed_job -e production stop
92
+ </pre>
93
+
94
+ Workers can be running on any computer, as long as they have access to the database and their clock is in sync. Keep in mind that each worker will check the database at least every 5 seconds.
95
+
96
+ You can also invoke @rake jobs:work@ which will start working off jobs. You can cancel the rake task with @CTRL-C@.
97
+
98
+ h2. Custom Jobs
99
+
100
+ Jobs are simple ruby objects with a method called perform. Any object which responds to perform can be stuffed into the jobs table. Job objects are serialized to yaml so that they can later be resurrected by the job runner.
101
+
102
+ <pre>
103
+ class NewsletterJob < Struct.new(:text, :emails)
104
+ def perform
105
+ emails.each { |e| NewsletterMailer.deliver_text_to_email(text, e) }
106
+ end
107
+ end
108
+
109
+ Delayed::Job.enqueue NewsletterJob.new('lorem ipsum...', Customers.find(:all).collect(&:email))
110
+ </pre>
111
+
112
+ h2. Gory Details
113
+
17
114
  The library evolves around a delayed_jobs table which looks as follows:
18
115
 
19
116
  create_table :delayed_jobs, :force => true do |table|
20
117
  table.integer :priority, :default => 0 # Allows some jobs to jump to the front of the queue
21
118
  table.integer :attempts, :default => 0 # Provides for retries, but still fail eventually.
22
119
  table.text :handler # YAML-encoded string of the object that will do work
23
- table.string :last_error # reason for last failure (See Note below)
120
+ table.text :last_error # reason for last failure (See Note below)
24
121
  table.datetime :run_at # When to run. Could be Time.now for immediately, or sometime in the future.
25
122
  table.datetime :locked_at # Set when a client is working on this object
26
123
  table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
@@ -41,58 +138,34 @@ Delayed::Job.destroy_failed_jobs = false. The failed jobs will be marked with no
41
138
 
42
139
  Here is an example of changing job parameters in Rails:
43
140
 
44
- # config/initializers/delayed_job_config.rb
45
- Delayed::Job.destroy_failed_jobs = false
46
- silence_warnings do
47
- Delayed::Job.const_set("MAX_ATTEMPTS", 3)
48
- Delayed::Job.const_set("MAX_RUN_TIME", 5.minutes)
49
- end
50
-
51
- Note: If your error messages are long, consider changing last_error field to a :text instead of a :string (255 character limit).
52
-
53
-
54
- h2. Usage
141
+ <pre>
142
+ # config/initializers/delayed_job_config.rb
143
+ Delayed::Job.destroy_failed_jobs = false
144
+ silence_warnings do
145
+ Delayed::Job.const_set("MAX_ATTEMPTS", 3)
146
+ Delayed::Job.const_set("MAX_RUN_TIME", 5.minutes)
147
+ end
148
+ </pre>
55
149
 
56
- Jobs are simple ruby objects with a method called perform. Any object which responds to perform can be stuffed into the jobs table.
57
- Job objects are serialized to yaml so that they can later be resurrected by the job runner.
58
-
59
- class NewsletterJob < Struct.new(:text, :emails)
60
- def perform
61
- emails.each { |e| NewsletterMailer.deliver_text_to_email(text, e) }
62
- end
63
- end
64
-
65
- Delayed::Job.enqueue NewsletterJob.new('lorem ipsum...', Customers.find(:all).collect(&:email))
66
-
67
- There is also a second way to get jobs in the queue: send_later.
68
-
69
-
70
- BatchImporter.new(Shop.find(1)).send_later(:import_massive_csv, massive_csv)
71
-
72
-
73
- This will simply create a Delayed::PerformableMethod job in the jobs table which serializes all the parameters you pass to it. There are some special smarts for active record objects
74
- which are stored as their text representation and loaded from the database fresh when the job is actually run later.
75
-
76
-
77
- h2. Running the jobs
150
+ h3. Cleaning up
78
151
 
79
- Run @script/generate delayed_job@ to add @script/delayed_job@. This script can then be used to manage a process which will start working off jobs.
152
+ You can invoke @rake jobs:clear@ to delete all jobs in the queue.
80
153
 
81
- # Runs two workers in separate processes.
82
- $ ruby script/delayed_job -e production -n 2 start
83
- $ ruby script/delayed_job -e production stop
154
+ h2. How to contribute
84
155
 
85
- You can invoke @rake jobs:work@ which will start working off jobs. You can cancel the rake task with @CTRL-C@.
156
+ If you find what looks like a bug:
86
157
 
87
- Workers can be running on any computer, as long as they have access to the database and their clock is in sync. You can even
88
- run multiple workers on per computer, but you must give each one a unique name. (TODO: put in an example)
89
- Keep in mind that each worker will check the database at least every 5 seconds.
158
+ # Check the GitHub issue tracker to see if anyone else has had the same issue.
159
+ http://github.com/collectiveidea/delayed_job/issues/
160
+ # If you don't see anything, create an issue with information on how to reproduce it.
90
161
 
91
- Note: The rake task will exit if the database has any network connectivity problems.
162
+ If you want to contribute an enhancement or a fix:
92
163
 
93
- h3. Cleaning up
94
-
95
- You can invoke @rake jobs:clear@ to delete all jobs in the queue.
164
+ # Fork the project on github.
165
+ http://github.com/collectiveidea/delayed_job/
166
+ # Make your changes with tests.
167
+ # Commit the changes without making changes to the Rakefile, VERSION, or any other files that aren't related to your enhancement or fix
168
+ # Send a pull request.
96
169
 
97
170
  h3. Changes
98
171
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.8.0
1
+ 1.8.1
data/delayed_job.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{delayed_job}
5
- s.version = "1.8.0"
5
+ s.version = "1.8.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Tobias L\303\274tke"]
9
- s.date = %q{2009-07-19}
9
+ s.date = %q{2009-09-06}
10
10
  s.description = %q{Delayed_job (or DJ) encapsulates the common pattern of asynchronously executing longer tasks in the background. It is a direct extraction from Shopify where the job table is responsible for a multitude of core tasks.}
11
11
  s.email = %q{tobi@leetsoft.com}
12
12
  s.extra_rdoc_files = [
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
27
27
  "lib/delayed/job.rb",
28
28
  "lib/delayed/message_sending.rb",
29
29
  "lib/delayed/performable_method.rb",
30
+ "lib/delayed/tasks.rb",
30
31
  "lib/delayed/worker.rb",
31
32
  "lib/delayed_job.rb",
32
33
  "recipes/delayed_job.rb",
@@ -34,8 +35,7 @@ Gem::Specification.new do |s|
34
35
  "spec/delayed_method_spec.rb",
35
36
  "spec/job_spec.rb",
36
37
  "spec/story_spec.rb",
37
- "tasks/jobs.rake",
38
- "tasks/tasks.rb"
38
+ "tasks/jobs.rake"
39
39
  ]
40
40
  s.homepage = %q{http://github.com/tobi/delayed_job/tree/master}
41
41
  s.rdoc_options = ["--main", "README.textile", "--inline-source", "--line-numbers"]
@@ -1,11 +1,22 @@
1
1
  class DelayedJobGenerator < Rails::Generator::Base
2
+ default_options :skip_migration => false
2
3
 
3
4
  def manifest
4
5
  record do |m|
5
6
  m.template 'script', 'script/delayed_job', :chmod => 0755
6
- m.migration_template "migration.rb", 'db/migrate',
7
- :migration_file_name => "create_delayed_jobs"
7
+ unless options[:skip_migration]
8
+ m.migration_template "migration.rb", 'db/migrate',
9
+ :migration_file_name => "create_delayed_jobs"
10
+ end
8
11
  end
9
12
  end
10
13
 
14
+ protected
15
+
16
+ def add_options!(opt)
17
+ opt.separator ''
18
+ opt.separator 'Options:'
19
+ opt.on("--skip-migration", "Don't generate a migration") { |v| options[:skip_migration] = v }
20
+ end
21
+
11
22
  end
@@ -1,7 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # Daemons sets pwd to /, so we have to explicitly set RAILS_ROOT
4
- RAILS_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
5
-
6
- require File.join(File.dirname(__FILE__), *%w(.. vendor plugins delayed_job lib delayed command))
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
4
+ require 'delayed/command'
7
5
  Delayed::Command.new(ARGV).daemonize
@@ -1,4 +1,3 @@
1
- require 'rubygems'
2
1
  require 'daemons'
3
2
  require 'optparse'
4
3
 
@@ -44,14 +43,14 @@ module Delayed
44
43
 
45
44
  def run(worker_name = nil)
46
45
  Dir.chdir(RAILS_ROOT)
47
- require File.join(RAILS_ROOT, 'config', 'environment')
48
46
 
49
- # Replace the default logger
50
- logger = Logger.new(File.join(RAILS_ROOT, 'log', 'delayed_job.log'))
51
- logger.level = ActiveRecord::Base.logger.level
52
- ActiveRecord::Base.logger = logger
53
- ActiveRecord::Base.clear_active_connections!
54
- Delayed::Worker.logger = logger
47
+ # Replace the default logger…too bad Rails doesn't make this easier
48
+ Rails.logger.instance_eval do
49
+ @log.reopen File.join(RAILS_ROOT, 'log', 'delayed_job.log')
50
+ end
51
+ Delayed::Worker.logger = Rails.logger
52
+ ActiveRecord::Base.connection.reconnect!
53
+
55
54
  Delayed::Job.worker_name = "#{worker_name} #{Delayed::Job.worker_name}"
56
55
 
57
56
  Delayed::Worker.new(@options).start
@@ -6,9 +6,10 @@ module Delayed
6
6
 
7
7
  module ClassMethods
8
8
  def handle_asynchronously(method)
9
- without_name = "#{method}_without_send_later"
10
- define_method("#{method}_with_send_later") do |*args|
11
- send_later(without_name, *args)
9
+ aliased_method, punctuation = method.to_s.sub(/([?!=])$/, ''), $1
10
+ with_method, without_method = "#{aliased_method}_with_send_later#{punctuation}", "#{aliased_method}_without_send_later#{punctuation}"
11
+ define_method(with_method) do |*args|
12
+ send_later(without_method, *args)
12
13
  end
13
14
  alias_method_chain method, :send_later
14
15
  end
File without changes
data/lib/delayed_job.rb CHANGED
@@ -9,5 +9,5 @@ Object.send(:include, Delayed::MessageSending)
9
9
  Module.send(:include, Delayed::MessageSending::ClassMethods)
10
10
 
11
11
  if defined?(Merb::Plugins)
12
- Merb::Plugins.add_rakefiles File.dirname(__FILE__) / '..' / 'tasks' / 'tasks'
12
+ Merb::Plugins.add_rakefiles File.dirname(__FILE__) / 'delayed' / 'tasks'
13
13
  end
data/tasks/jobs.rake CHANGED
@@ -1 +1 @@
1
- require File.join(File.dirname(__FILE__), 'tasks')
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'delayed', 'tasks'))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: collectiveidea-delayed_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Tobias L\xC3\xBCtke"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-19 00:00:00 -07:00
12
+ date: 2009-09-06 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -36,6 +36,7 @@ files:
36
36
  - lib/delayed/job.rb
37
37
  - lib/delayed/message_sending.rb
38
38
  - lib/delayed/performable_method.rb
39
+ - lib/delayed/tasks.rb
39
40
  - lib/delayed/worker.rb
40
41
  - lib/delayed_job.rb
41
42
  - recipes/delayed_job.rb
@@ -44,9 +45,9 @@ files:
44
45
  - spec/job_spec.rb
45
46
  - spec/story_spec.rb
46
47
  - tasks/jobs.rake
47
- - tasks/tasks.rb
48
48
  has_rdoc: false
49
49
  homepage: http://github.com/tobi/delayed_job/tree/master
50
+ licenses:
50
51
  post_install_message:
51
52
  rdoc_options:
52
53
  - --main
@@ -70,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
70
71
  requirements: []
71
72
 
72
73
  rubyforge_project:
73
- rubygems_version: 1.2.0
74
+ rubygems_version: 1.3.5
74
75
  signing_key:
75
76
  specification_version: 3
76
77
  summary: Database-backed asynchronous priority queue system -- Extracted from Shopify