delayed_job 2.1.0.pre2 → 2.1.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/README.textile +78 -43
- data/lib/delayed/backend/active_record.rb +14 -29
- data/lib/delayed/backend/base.rb +66 -37
- data/lib/delayed/backend/shared_spec.rb +188 -191
- data/lib/delayed/command.rb +3 -2
- data/lib/delayed/deserialization_error.rb +4 -0
- data/lib/delayed/message_sending.rb +19 -11
- data/lib/delayed/performable_mailer.rb +21 -0
- data/lib/delayed/performable_method.rb +19 -15
- data/lib/delayed/recipes.rb +6 -2
- data/lib/delayed/serialization/active_record.rb +13 -0
- data/lib/delayed/worker.rb +31 -40
- data/lib/delayed_job.rb +4 -2
- data/spec/active_record_job_spec.rb +4 -4
- data/spec/database.yml +4 -0
- data/spec/message_sending_spec.rb +42 -4
- data/spec/performable_mailer_spec.rb +46 -0
- data/spec/performable_method_spec.rb +27 -11
- data/spec/sample_jobs.rb +27 -19
- data/spec/spec_helper.rb +10 -8
- metadata +57 -21
- data/generators/delayed_job/delayed_job_generator.rb +0 -22
- data/generators/delayed_job/templates/migration.rb +0 -21
- data/generators/delayed_job/templates/script +0 -5
- data/init.rb +0 -1
- data/rails/init.rb +0 -5
- data/tasks/jobs.rake +0 -1
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'action_mailer'
|
4
|
+
class MyMailer < ActionMailer::Base
|
5
|
+
def signup(email)
|
6
|
+
mail :to => email, :subject => "Delaying Emails"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ActionMailer::Base do
|
11
|
+
describe "delay" do
|
12
|
+
it "should enqueue a PerformableEmail job" do
|
13
|
+
lambda {
|
14
|
+
job = MyMailer.delay.signup('john@example.com')
|
15
|
+
job.payload_object.class.should == Delayed::PerformableMailer
|
16
|
+
job.payload_object.method_name.should == :signup
|
17
|
+
job.payload_object.args.should == ['john@example.com']
|
18
|
+
}.should change { Delayed::Job.count }.by(1)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "delay on a mail object" do
|
23
|
+
it "should raise an exception" do
|
24
|
+
lambda {
|
25
|
+
MyMailer.signup('john@example.com').delay
|
26
|
+
}.should raise_error(RuntimeError)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe Delayed::PerformableMailer do
|
31
|
+
describe "perform" do
|
32
|
+
before do
|
33
|
+
@email = mock('email', :deliver => true)
|
34
|
+
@mailer_class = mock('MailerClass', :signup => @email)
|
35
|
+
@mailer = Delayed::PerformableMailer.new(@mailer_class, :signup, ['john@example.com'])
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should call the method and #deliver on the mailer" do
|
39
|
+
@mailer_class.should_receive(:signup).with('john@example.com')
|
40
|
+
@email.should_receive(:deliver)
|
41
|
+
@mailer.perform
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -5,28 +5,21 @@ describe Delayed::PerformableMethod do
|
|
5
5
|
before do
|
6
6
|
@method = Delayed::PerformableMethod.new("foo", :count, ['o'])
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
context "with the persisted record cannot be found" do
|
10
10
|
before do
|
11
11
|
@method.object = nil
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
it "should be a no-op if object is nil" do
|
15
15
|
lambda { @method.perform }.should_not raise_error
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
it "should call the method on the object" do
|
20
20
|
@method.object.should_receive(:count).with('o')
|
21
21
|
@method.perform
|
22
22
|
end
|
23
|
-
|
24
|
-
it "should respond to on_permanent_failure when implemented and target object is called via object.delay.do_something" do
|
25
|
-
@method = Delayed::PerformableMethod.new(OnPermanentFailureJob.new, :perform, [])
|
26
|
-
@method.respond_to?(:on_permanent_failure).should be_true
|
27
|
-
@method.object.should_receive(:on_permanent_failure)
|
28
|
-
@method.on_permanent_failure
|
29
|
-
end
|
30
23
|
end
|
31
24
|
|
32
25
|
it "should raise a NoMethodError if target method doesn't exist" do
|
@@ -34,7 +27,7 @@ describe Delayed::PerformableMethod do
|
|
34
27
|
Delayed::PerformableMethod.new(Object, :method_that_does_not_exist, [])
|
35
28
|
}.should raise_error(NoMethodError)
|
36
29
|
end
|
37
|
-
|
30
|
+
|
38
31
|
it "should not raise NoMethodError if target method is private" do
|
39
32
|
clazz = Class.new do
|
40
33
|
def private_method
|
@@ -45,4 +38,27 @@ describe Delayed::PerformableMethod do
|
|
45
38
|
Delayed::PerformableMethod.new(clazz.new, :private_method, [])
|
46
39
|
}.should_not raise_error(NoMethodError)
|
47
40
|
end
|
41
|
+
|
42
|
+
describe "hooks" do
|
43
|
+
%w(enqueue before after success).each do |hook|
|
44
|
+
it "should delegate #{hook} hook to object" do
|
45
|
+
story = Story.new
|
46
|
+
story.should_receive(hook).with(an_instance_of(Delayed::Job))
|
47
|
+
story.delay.tell.invoke_job
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should delegate error hook to object" do
|
52
|
+
story = Story.new
|
53
|
+
story.should_receive(:error).with(an_instance_of(Delayed::Job), an_instance_of(RuntimeError))
|
54
|
+
story.should_receive(:tell).and_raise(RuntimeError)
|
55
|
+
lambda { story.delay.tell.invoke_job }.should raise_error
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should delegate failure hook to object" do
|
59
|
+
method = Delayed::PerformableMethod.new("object", :size, [])
|
60
|
+
method.object.should_receive(:failure)
|
61
|
+
method.failure
|
62
|
+
end
|
63
|
+
end
|
48
64
|
end
|
data/spec/sample_jobs.rb
CHANGED
@@ -12,50 +12,58 @@ end
|
|
12
12
|
class ErrorJob
|
13
13
|
cattr_accessor :runs; self.runs = 0
|
14
14
|
def perform; raise 'did not work'; end
|
15
|
-
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class CustomRescheduleJob < Struct.new(:offset)
|
18
|
+
cattr_accessor :runs; self.runs = 0
|
19
|
+
def perform; raise 'did not work'; end
|
20
|
+
def reschedule_at(time, attempts); time + offset; end
|
21
|
+
end
|
16
22
|
|
17
23
|
class LongRunningJob
|
18
24
|
def perform; sleep 250; end
|
19
25
|
end
|
20
26
|
|
21
27
|
class OnPermanentFailureJob < SimpleJob
|
22
|
-
def
|
28
|
+
def failure
|
23
29
|
end
|
24
30
|
end
|
25
31
|
|
26
32
|
module M
|
27
33
|
class ModuleJob
|
28
34
|
cattr_accessor :runs; self.runs = 0
|
29
|
-
def perform; @@runs += 1; end
|
35
|
+
def perform; @@runs += 1; end
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
33
|
-
class
|
39
|
+
class CallbackJob
|
34
40
|
cattr_accessor :messages
|
35
41
|
|
42
|
+
def enqueue(job)
|
43
|
+
self.class.messages << 'enqueue'
|
44
|
+
end
|
45
|
+
|
36
46
|
def before(job)
|
37
|
-
|
47
|
+
self.class.messages << 'before'
|
38
48
|
end
|
39
|
-
|
49
|
+
|
40
50
|
def perform
|
41
|
-
|
51
|
+
self.class.messages << 'perform'
|
42
52
|
end
|
43
|
-
|
44
|
-
def after(job
|
45
|
-
|
53
|
+
|
54
|
+
def after(job)
|
55
|
+
self.class.messages << 'after'
|
46
56
|
end
|
47
|
-
|
57
|
+
|
48
58
|
def success(job)
|
49
|
-
|
59
|
+
self.class.messages << 'success'
|
50
60
|
end
|
51
|
-
|
52
|
-
def
|
53
|
-
|
61
|
+
|
62
|
+
def error(job, error)
|
63
|
+
self.class.messages << "error: #{error.class}"
|
54
64
|
end
|
55
|
-
end
|
56
65
|
|
57
|
-
|
58
|
-
|
59
|
-
raise "failure job"
|
66
|
+
def failure(job)
|
67
|
+
self.class.messages << 'failure'
|
60
68
|
end
|
61
69
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,20 +2,22 @@ $:.unshift(File.dirname(__FILE__) + '/../lib')
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'bundler/setup'
|
5
|
-
require '
|
5
|
+
require 'rspec'
|
6
6
|
require 'logger'
|
7
7
|
|
8
|
-
|
8
|
+
require 'active_record'
|
9
|
+
require 'action_mailer'
|
9
10
|
|
10
11
|
require 'delayed_job'
|
11
12
|
require 'delayed/backend/shared_spec'
|
12
13
|
|
13
14
|
Delayed::Worker.logger = Logger.new('/tmp/dj.log')
|
14
|
-
RAILS_ENV = 'test'
|
15
|
-
|
16
|
-
require 'active_record'
|
15
|
+
ENV['RAILS_ENV'] = 'test'
|
16
|
+
require 'rails'
|
17
17
|
|
18
|
-
|
18
|
+
config = YAML.load(File.read('spec/database.yml'))
|
19
|
+
ActiveRecord::Base.configurations = {'test' => config['mysql']}
|
20
|
+
ActiveRecord::Base.establish_connection
|
19
21
|
ActiveRecord::Base.logger = Delayed::Worker.logger
|
20
22
|
ActiveRecord::Migration.verbose = false
|
21
23
|
|
@@ -41,9 +43,9 @@ end
|
|
41
43
|
|
42
44
|
# Purely useful for test cases...
|
43
45
|
class Story < ActiveRecord::Base
|
44
|
-
def tell; text; end
|
46
|
+
def tell; text; end
|
45
47
|
def whatever(n, _); tell*n; end
|
46
|
-
|
48
|
+
|
47
49
|
handle_asynchronously :whatever
|
48
50
|
end
|
49
51
|
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delayed_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
4
|
+
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 2
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
|
10
|
-
version: 2.1.0.pre2
|
8
|
+
- 1
|
9
|
+
version: 2.1.1
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Brandon Keepers
|
@@ -16,7 +15,7 @@ autorequire:
|
|
16
15
|
bindir: bin
|
17
16
|
cert_chain: []
|
18
17
|
|
19
|
-
date: 2010-
|
18
|
+
date: 2010-11-14 00:00:00 -06:00
|
20
19
|
default_executable:
|
21
20
|
dependencies:
|
22
21
|
- !ruby/object:Gem::Dependency
|
@@ -49,15 +48,16 @@ dependencies:
|
|
49
48
|
prerelease: false
|
50
49
|
requirement: &id003 !ruby/object:Gem::Requirement
|
51
50
|
requirements:
|
52
|
-
- -
|
51
|
+
- - ~>
|
53
52
|
- !ruby/object:Gem::Version
|
54
53
|
segments:
|
54
|
+
- 2
|
55
55
|
- 0
|
56
|
-
version: "0"
|
56
|
+
version: "2.0"
|
57
57
|
type: :development
|
58
58
|
version_requirements: *id003
|
59
59
|
- !ruby/object:Gem::Dependency
|
60
|
-
name:
|
60
|
+
name: rake
|
61
61
|
prerelease: false
|
62
62
|
requirement: &id004 !ruby/object:Gem::Requirement
|
63
63
|
requirements:
|
@@ -69,9 +69,22 @@ dependencies:
|
|
69
69
|
type: :development
|
70
70
|
version_requirements: *id004
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
|
-
name:
|
72
|
+
name: rails
|
73
73
|
prerelease: false
|
74
74
|
requirement: &id005 !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ~>
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
segments:
|
79
|
+
- 3
|
80
|
+
- 0
|
81
|
+
version: "3.0"
|
82
|
+
type: :development
|
83
|
+
version_requirements: *id005
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: sqlite3-ruby
|
86
|
+
prerelease: false
|
87
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
75
88
|
requirements:
|
76
89
|
- - ">="
|
77
90
|
- !ruby/object:Gem::Version
|
@@ -79,7 +92,31 @@ dependencies:
|
|
79
92
|
- 0
|
80
93
|
version: "0"
|
81
94
|
type: :development
|
82
|
-
version_requirements: *
|
95
|
+
version_requirements: *id006
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: ruby-debug
|
98
|
+
prerelease: false
|
99
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
type: :development
|
107
|
+
version_requirements: *id007
|
108
|
+
- !ruby/object:Gem::Dependency
|
109
|
+
name: mysql
|
110
|
+
prerelease: false
|
111
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
segments:
|
116
|
+
- 0
|
117
|
+
version: "0"
|
118
|
+
type: :development
|
119
|
+
version_requirements: *id008
|
83
120
|
description: |-
|
84
121
|
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.
|
85
122
|
|
@@ -94,17 +131,17 @@ extra_rdoc_files:
|
|
94
131
|
files:
|
95
132
|
- contrib/delayed_job.monitrc
|
96
133
|
- contrib/delayed_job_multiple.monitrc
|
97
|
-
- generators/delayed_job/delayed_job_generator.rb
|
98
|
-
- generators/delayed_job/templates/migration.rb
|
99
|
-
- generators/delayed_job/templates/script
|
100
134
|
- lib/delayed/backend/active_record.rb
|
101
135
|
- lib/delayed/backend/base.rb
|
102
136
|
- lib/delayed/backend/shared_spec.rb
|
103
137
|
- lib/delayed/command.rb
|
138
|
+
- lib/delayed/deserialization_error.rb
|
104
139
|
- lib/delayed/message_sending.rb
|
140
|
+
- lib/delayed/performable_mailer.rb
|
105
141
|
- lib/delayed/performable_method.rb
|
106
142
|
- lib/delayed/railtie.rb
|
107
143
|
- lib/delayed/recipes.rb
|
144
|
+
- lib/delayed/serialization/active_record.rb
|
108
145
|
- lib/delayed/tasks.rb
|
109
146
|
- lib/delayed/worker.rb
|
110
147
|
- lib/delayed/yaml_ext.rb
|
@@ -112,19 +149,18 @@ files:
|
|
112
149
|
- lib/generators/delayed_job/delayed_job_generator.rb
|
113
150
|
- lib/generators/delayed_job/templates/migration.rb
|
114
151
|
- lib/generators/delayed_job/templates/script
|
115
|
-
- rails/init.rb
|
116
152
|
- recipes/delayed_job.rb
|
117
153
|
- spec/active_record_job_spec.rb
|
118
154
|
- spec/autoloaded/clazz.rb
|
119
155
|
- spec/autoloaded/struct.rb
|
156
|
+
- spec/database.yml
|
120
157
|
- spec/message_sending_spec.rb
|
158
|
+
- spec/performable_mailer_spec.rb
|
121
159
|
- spec/performable_method_spec.rb
|
122
160
|
- spec/sample_jobs.rb
|
123
161
|
- spec/spec_helper.rb
|
124
162
|
- spec/worker_spec.rb
|
125
163
|
- spec/yaml_ext_spec.rb
|
126
|
-
- tasks/jobs.rake
|
127
|
-
- init.rb
|
128
164
|
- MIT-LICENSE
|
129
165
|
- README.textile
|
130
166
|
has_rdoc: true
|
@@ -148,13 +184,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
148
184
|
version: "0"
|
149
185
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
186
|
requirements:
|
151
|
-
- - "
|
187
|
+
- - ">="
|
152
188
|
- !ruby/object:Gem::Version
|
153
189
|
segments:
|
154
|
-
-
|
155
|
-
|
156
|
-
- 1
|
157
|
-
version: 1.3.1
|
190
|
+
- 0
|
191
|
+
version: "0"
|
158
192
|
requirements: []
|
159
193
|
|
160
194
|
rubyforge_project:
|
@@ -166,7 +200,9 @@ test_files:
|
|
166
200
|
- spec/active_record_job_spec.rb
|
167
201
|
- spec/autoloaded/clazz.rb
|
168
202
|
- spec/autoloaded/struct.rb
|
203
|
+
- spec/database.yml
|
169
204
|
- spec/message_sending_spec.rb
|
205
|
+
- spec/performable_mailer_spec.rb
|
170
206
|
- spec/performable_method_spec.rb
|
171
207
|
- spec/sample_jobs.rb
|
172
208
|
- spec/spec_helper.rb
|
@@ -1,22 +0,0 @@
|
|
1
|
-
class DelayedJobGenerator < Rails::Generator::Base
|
2
|
-
default_options :skip_migration => false
|
3
|
-
|
4
|
-
def manifest
|
5
|
-
record do |m|
|
6
|
-
m.template 'script', 'script/delayed_job', :chmod => 0755
|
7
|
-
if !options[:skip_migration] && defined?(ActiveRecord)
|
8
|
-
m.migration_template "migration.rb", 'db/migrate',
|
9
|
-
:migration_file_name => "create_delayed_jobs"
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
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
|
-
|
22
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
class CreateDelayedJobs < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :delayed_jobs, :force => true do |table|
|
4
|
-
table.integer :priority, :default => 0 # Allows some jobs to jump to the front of the queue
|
5
|
-
table.integer :attempts, :default => 0 # Provides for retries, but still fail eventually.
|
6
|
-
table.text :handler # YAML-encoded string of the object that will do work
|
7
|
-
table.text :last_error # reason for last failure (See Note below)
|
8
|
-
table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
|
9
|
-
table.datetime :locked_at # Set when a client is working on this object
|
10
|
-
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
|
11
|
-
table.string :locked_by # Who is working on this object (if locked)
|
12
|
-
table.timestamps
|
13
|
-
end
|
14
|
-
|
15
|
-
add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.down
|
19
|
-
drop_table :delayed_jobs
|
20
|
-
end
|
21
|
-
end
|