delayed_job 4.0.2 → 4.0.3
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.
- checksums.yaml +5 -13
- data/CHANGELOG.md +7 -0
- data/README.md +12 -7
- data/Rakefile +6 -1
- data/delayed_job.gemspec +5 -5
- data/lib/delayed/backend/base.rb +18 -20
- data/lib/delayed/backend/shared_spec.rb +139 -138
- data/lib/delayed/command.rb +75 -40
- data/lib/delayed/exceptions.rb +2 -1
- data/lib/delayed/lifecycle.rb +12 -11
- data/lib/delayed/message_sending.rb +9 -10
- data/lib/delayed/performable_mailer.rb +2 -2
- data/lib/delayed/performable_method.rb +2 -2
- data/lib/delayed/psych_ext.rb +29 -93
- data/lib/delayed/recipes.rb +5 -5
- data/lib/delayed/serialization/active_record.rb +11 -9
- data/lib/delayed/syck_ext.rb +3 -3
- data/lib/delayed/tasks.rb +5 -5
- data/lib/delayed/worker.rb +42 -42
- data/lib/generators/delayed_job/delayed_job_generator.rb +2 -3
- data/spec/delayed/backend/test.rb +22 -17
- data/spec/delayed/command_spec.rb +57 -0
- data/spec/helper.rb +25 -12
- data/spec/lifecycle_spec.rb +23 -15
- data/spec/message_sending_spec.rb +34 -34
- data/spec/performable_mailer_spec.rb +11 -11
- data/spec/performable_method_spec.rb +24 -26
- data/spec/psych_ext_spec.rb +12 -0
- data/spec/sample_jobs.rb +46 -18
- data/spec/test_backend_spec.rb +3 -3
- data/spec/worker_spec.rb +27 -27
- data/spec/yaml_ext_spec.rb +16 -16
- metadata +12 -8
data/spec/helper.rb
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'coveralls'
|
3
|
+
|
4
|
+
SimpleCov.formatters = [SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter]
|
5
|
+
|
6
|
+
SimpleCov.start do
|
7
|
+
add_filter '/spec/'
|
8
|
+
# Each version of ruby and version of rails test different things
|
9
|
+
# This should probably just be removed.
|
10
|
+
minimum_coverage(85.0)
|
11
|
+
end
|
12
|
+
|
1
13
|
require 'logger'
|
2
14
|
require 'rspec'
|
3
15
|
|
@@ -8,18 +20,15 @@ require 'active_record'
|
|
8
20
|
require 'delayed_job'
|
9
21
|
require 'delayed/backend/shared_spec'
|
10
22
|
|
11
|
-
require 'simplecov'
|
12
|
-
require 'coveralls'
|
13
|
-
|
14
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
15
|
-
SimpleCov::Formatter::HTMLFormatter,
|
16
|
-
Coveralls::SimpleCov::Formatter
|
17
|
-
]
|
18
|
-
SimpleCov.start
|
19
|
-
|
20
23
|
Delayed::Worker.logger = Logger.new('/tmp/dj.log')
|
21
24
|
ENV['RAILS_ENV'] = 'test'
|
22
25
|
|
26
|
+
module Rails
|
27
|
+
def self.root
|
28
|
+
'.'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
23
32
|
Delayed::Worker.backend = :test
|
24
33
|
|
25
34
|
# Add this directory so the ActiveSupport autoloading works
|
@@ -28,7 +37,6 @@ ActiveSupport::Dependencies.autoload_paths << File.dirname(__FILE__)
|
|
28
37
|
# Add this to simulate Railtie initializer being executed
|
29
38
|
ActionMailer::Base.extend(Delayed::DelayMail)
|
30
39
|
|
31
|
-
|
32
40
|
# Used to test interactions between DJ and an ORM
|
33
41
|
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
|
34
42
|
ActiveRecord::Base.logger = Delayed::Worker.logger
|
@@ -43,8 +51,13 @@ end
|
|
43
51
|
|
44
52
|
class Story < ActiveRecord::Base
|
45
53
|
self.primary_key = 'story_id'
|
46
|
-
def tell
|
47
|
-
|
54
|
+
def tell
|
55
|
+
text
|
56
|
+
end
|
57
|
+
|
58
|
+
def whatever(n, _)
|
59
|
+
tell * n
|
60
|
+
end
|
48
61
|
default_scope { where(:scoped => true) }
|
49
62
|
|
50
63
|
handle_asynchronously :whatever
|
data/spec/lifecycle_spec.rb
CHANGED
@@ -2,36 +2,36 @@ require 'helper'
|
|
2
2
|
|
3
3
|
describe Delayed::Lifecycle do
|
4
4
|
let(:lifecycle) { Delayed::Lifecycle.new }
|
5
|
-
let(:callback) { lambda {|*
|
5
|
+
let(:callback) { lambda { |*_args| } }
|
6
6
|
let(:arguments) { [1] }
|
7
7
|
let(:behavior) { double(Object, :before! => nil, :after! => nil, :inside! => nil) }
|
8
|
-
let(:wrapped_block) {
|
8
|
+
let(:wrapped_block) { proc { behavior.inside! } }
|
9
9
|
|
10
|
-
describe
|
10
|
+
describe 'before callbacks' do
|
11
11
|
before(:each) do
|
12
12
|
lifecycle.before(:execute, &callback)
|
13
13
|
end
|
14
14
|
|
15
|
-
it
|
15
|
+
it 'executes before wrapped block' do
|
16
16
|
expect(callback).to receive(:call).with(*arguments).ordered
|
17
17
|
expect(behavior).to receive(:inside!).ordered
|
18
18
|
lifecycle.run_callbacks :execute, *arguments, &wrapped_block
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
describe
|
22
|
+
describe 'after callbacks' do
|
23
23
|
before(:each) do
|
24
24
|
lifecycle.after(:execute, &callback)
|
25
25
|
end
|
26
26
|
|
27
|
-
it
|
27
|
+
it 'executes after wrapped block' do
|
28
28
|
expect(behavior).to receive(:inside!).ordered
|
29
29
|
expect(callback).to receive(:call).with(*arguments).ordered
|
30
30
|
lifecycle.run_callbacks :execute, *arguments, &wrapped_block
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
describe
|
34
|
+
describe 'around callbacks' do
|
35
35
|
before(:each) do
|
36
36
|
lifecycle.around(:execute) do |*args, &block|
|
37
37
|
behavior.before!
|
@@ -40,28 +40,36 @@ describe Delayed::Lifecycle do
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
it
|
43
|
+
it 'wraps a block' do
|
44
44
|
expect(behavior).to receive(:before!).ordered
|
45
45
|
expect(behavior).to receive(:inside!).ordered
|
46
46
|
expect(behavior).to receive(:after!).ordered
|
47
47
|
lifecycle.run_callbacks :execute, *arguments, &wrapped_block
|
48
48
|
end
|
49
49
|
|
50
|
-
it
|
50
|
+
it 'executes multiple callbacks in order' do
|
51
51
|
expect(behavior).to receive(:one).ordered
|
52
52
|
expect(behavior).to receive(:two).ordered
|
53
53
|
expect(behavior).to receive(:three).ordered
|
54
54
|
|
55
|
-
lifecycle.around(:execute)
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
lifecycle.around(:execute) do |*args, &block|
|
56
|
+
behavior.one
|
57
|
+
block.call(*args)
|
58
|
+
end
|
59
|
+
lifecycle.around(:execute) do |*args, &block|
|
60
|
+
behavior.two
|
61
|
+
block.call(*args)
|
62
|
+
end
|
63
|
+
lifecycle.around(:execute) do |*args, &block|
|
64
|
+
behavior.three
|
65
|
+
block.call(*args)
|
66
|
+
end
|
59
67
|
lifecycle.run_callbacks(:execute, *arguments, &wrapped_block)
|
60
68
|
end
|
61
69
|
end
|
62
70
|
|
63
|
-
it
|
71
|
+
it 'raises if callback is executed with wrong number of parameters' do
|
64
72
|
lifecycle.before(:execute, &callback)
|
65
|
-
expect { lifecycle.run_callbacks(:execute, 1,2,3) {} }.to raise_error(ArgumentError, /1 parameter/)
|
73
|
+
expect { lifecycle.run_callbacks(:execute, 1, 2, 3) {} }.to raise_error(ArgumentError, /1 parameter/)
|
66
74
|
end
|
67
75
|
end
|
@@ -1,35 +1,35 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe Delayed::MessageSending do
|
4
|
-
describe
|
4
|
+
describe 'handle_asynchronously' do
|
5
5
|
class Story
|
6
|
-
def tell!(
|
6
|
+
def tell!(_arg); end
|
7
7
|
handle_asynchronously :tell!
|
8
8
|
end
|
9
9
|
|
10
|
-
it
|
10
|
+
it 'aliases original method' do
|
11
11
|
expect(Story.new).to respond_to(:tell_without_delay!)
|
12
12
|
expect(Story.new).to respond_to(:tell_with_delay!)
|
13
13
|
end
|
14
14
|
|
15
|
-
it
|
15
|
+
it 'creates a PerformableMethod' do
|
16
16
|
story = Story.create
|
17
|
-
expect
|
17
|
+
expect do
|
18
18
|
job = story.tell!(1)
|
19
19
|
expect(job.payload_object.class).to eq(Delayed::PerformableMethod)
|
20
20
|
expect(job.payload_object.method_name).to eq(:tell_without_delay!)
|
21
21
|
expect(job.payload_object.args).to eq([1])
|
22
|
-
|
22
|
+
end.to change { Delayed::Job.count }
|
23
23
|
end
|
24
24
|
|
25
|
-
describe
|
25
|
+
describe 'with options' do
|
26
26
|
class Fable
|
27
27
|
cattr_accessor :importance
|
28
|
-
def tell;end
|
29
|
-
handle_asynchronously :tell, :priority =>
|
28
|
+
def tell; end
|
29
|
+
handle_asynchronously :tell, :priority => proc { importance }
|
30
30
|
end
|
31
31
|
|
32
|
-
it
|
32
|
+
it 'sets the priority based on the Fable importance' do
|
33
33
|
Fable.importance = 10
|
34
34
|
job = Fable.new.tell
|
35
35
|
expect(job.priority).to eq(10)
|
@@ -39,29 +39,29 @@ describe Delayed::MessageSending do
|
|
39
39
|
expect(job.priority).to eq(20)
|
40
40
|
end
|
41
41
|
|
42
|
-
describe
|
42
|
+
describe 'using a proc with parameters' do
|
43
43
|
class Yarn
|
44
44
|
attr_accessor :importance
|
45
45
|
def spin
|
46
46
|
end
|
47
|
-
handle_asynchronously :spin, :priority =>
|
47
|
+
handle_asynchronously :spin, :priority => proc { |y| y.importance }
|
48
48
|
end
|
49
49
|
|
50
|
-
it
|
51
|
-
job = Yarn.new.tap {|y| y.importance = 10 }.spin
|
50
|
+
it 'sets the priority based on the Fable importance' do
|
51
|
+
job = Yarn.new.tap { |y| y.importance = 10 }.spin
|
52
52
|
expect(job.priority).to eq(10)
|
53
53
|
|
54
|
-
job = Yarn.new.tap {|y| y.importance = 20 }.spin
|
54
|
+
job = Yarn.new.tap { |y| y.importance = 20 }.spin
|
55
55
|
expect(job.priority).to eq(20)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
context
|
61
|
+
context 'delay' do
|
62
62
|
class FairyTail
|
63
63
|
attr_accessor :happy_ending
|
64
|
-
def self.princesses;end
|
64
|
+
def self.princesses; end
|
65
65
|
def tell
|
66
66
|
@happy_ending = true
|
67
67
|
end
|
@@ -71,52 +71,52 @@ describe Delayed::MessageSending do
|
|
71
71
|
Delayed::Worker.default_queue_name = nil
|
72
72
|
end
|
73
73
|
|
74
|
-
it
|
75
|
-
expect
|
76
|
-
job =
|
74
|
+
it 'creates a new PerformableMethod job' do
|
75
|
+
expect do
|
76
|
+
job = 'hello'.delay.count('l')
|
77
77
|
expect(job.payload_object.class).to eq(Delayed::PerformableMethod)
|
78
78
|
expect(job.payload_object.method_name).to eq(:count)
|
79
79
|
expect(job.payload_object.args).to eq(['l'])
|
80
|
-
|
80
|
+
end.to change { Delayed::Job.count }.by(1)
|
81
81
|
end
|
82
82
|
|
83
|
-
it
|
83
|
+
it 'sets default priority' do
|
84
84
|
Delayed::Worker.default_priority = 99
|
85
85
|
job = FairyTail.delay.to_s
|
86
86
|
expect(job.priority).to eq(99)
|
87
87
|
end
|
88
88
|
|
89
|
-
it
|
89
|
+
it 'sets default queue name' do
|
90
90
|
Delayed::Worker.default_queue_name = 'abbazabba'
|
91
91
|
job = FairyTail.delay.to_s
|
92
92
|
expect(job.queue).to eq('abbazabba')
|
93
93
|
end
|
94
94
|
|
95
|
-
it
|
95
|
+
it 'sets job options' do
|
96
96
|
run_at = Time.parse('2010-05-03 12:55 AM')
|
97
97
|
job = FairyTail.delay(:priority => 20, :run_at => run_at).to_s
|
98
98
|
expect(job.run_at).to eq(run_at)
|
99
99
|
expect(job.priority).to eq(20)
|
100
100
|
end
|
101
101
|
|
102
|
-
it
|
102
|
+
it 'does not delay the job when delay_jobs is false' do
|
103
103
|
Delayed::Worker.delay_jobs = false
|
104
104
|
fairy_tail = FairyTail.new
|
105
|
-
expect
|
106
|
-
expect
|
105
|
+
expect do
|
106
|
+
expect do
|
107
107
|
fairy_tail.delay.tell
|
108
|
-
|
109
|
-
|
108
|
+
end.to change(fairy_tail, :happy_ending).from(nil).to(true)
|
109
|
+
end.not_to change { Delayed::Job.count }
|
110
110
|
end
|
111
111
|
|
112
|
-
it
|
112
|
+
it 'does delay the job when delay_jobs is true' do
|
113
113
|
Delayed::Worker.delay_jobs = true
|
114
114
|
fairy_tail = FairyTail.new
|
115
|
-
expect
|
116
|
-
expect
|
115
|
+
expect do
|
116
|
+
expect do
|
117
117
|
fairy_tail.delay.tell
|
118
|
-
|
119
|
-
|
118
|
+
end.not_to change(fairy_tail, :happy_ending)
|
119
|
+
end.to change { Delayed::Job.count }.by(1)
|
120
120
|
end
|
121
121
|
end
|
122
122
|
end
|
@@ -3,33 +3,33 @@ require 'helper'
|
|
3
3
|
require 'action_mailer'
|
4
4
|
class MyMailer < ActionMailer::Base
|
5
5
|
def signup(email)
|
6
|
-
mail :to => email, :subject =>
|
6
|
+
mail :to => email, :subject => 'Delaying Emails', :from => 'delayedjob@example.com', :body => 'Delaying Emails Body'
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
10
|
describe ActionMailer::Base do
|
11
|
-
describe
|
12
|
-
it
|
13
|
-
expect
|
11
|
+
describe 'delay' do
|
12
|
+
it 'enqueues a PerformableEmail job' do
|
13
|
+
expect do
|
14
14
|
job = MyMailer.delay.signup('john@example.com')
|
15
15
|
expect(job.payload_object.class).to eq(Delayed::PerformableMailer)
|
16
16
|
expect(job.payload_object.method_name).to eq(:signup)
|
17
17
|
expect(job.payload_object.args).to eq(['john@example.com'])
|
18
|
-
|
18
|
+
end.to change { Delayed::Job.count }.by(1)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
describe
|
23
|
-
it
|
24
|
-
expect
|
22
|
+
describe 'delay on a mail object' do
|
23
|
+
it 'raises an exception' do
|
24
|
+
expect do
|
25
25
|
MyMailer.signup('john@example.com').delay
|
26
|
-
|
26
|
+
end.to raise_error(RuntimeError)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
30
|
describe Delayed::PerformableMailer do
|
31
|
-
describe
|
32
|
-
it
|
31
|
+
describe 'perform' do
|
32
|
+
it 'calls the method and #deliver on the mailer' do
|
33
33
|
email = double('email', :deliver => true)
|
34
34
|
mailer_class = double('MailerClass', :signup => email)
|
35
35
|
mailer = Delayed::PerformableMailer.new(mailer_class, :signup, ['john@example.com'])
|
@@ -1,46 +1,44 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe Delayed::PerformableMethod do
|
4
|
-
describe
|
4
|
+
describe 'perform' do
|
5
5
|
before do
|
6
|
-
@method = Delayed::PerformableMethod.new(
|
6
|
+
@method = Delayed::PerformableMethod.new('foo', :count, ['o'])
|
7
7
|
end
|
8
8
|
|
9
|
-
context
|
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
|
-
it
|
15
|
-
expect{@method.perform}.not_to raise_error
|
14
|
+
it 'does nothing if object is nil' do
|
15
|
+
expect { @method.perform }.not_to raise_error
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
it
|
19
|
+
it 'calls the method on the object' do
|
20
20
|
expect(@method.object).to receive(:count).with('o')
|
21
21
|
@method.perform
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
it "raises a NoMethodError if target method doesn't exist" do
|
26
|
-
expect
|
26
|
+
expect do
|
27
27
|
Delayed::PerformableMethod.new(Object, :method_that_does_not_exist, [])
|
28
|
-
|
28
|
+
end.to raise_error(NoMethodError)
|
29
29
|
end
|
30
30
|
|
31
|
-
it
|
31
|
+
it 'does not raise NoMethodError if target method is private' do
|
32
32
|
clazz = Class.new do
|
33
33
|
def private_method
|
34
34
|
end
|
35
35
|
private :private_method
|
36
36
|
end
|
37
|
-
expect {
|
38
|
-
Delayed::PerformableMethod.new(clazz.new, :private_method, [])
|
39
|
-
}.not_to raise_error
|
37
|
+
expect { Delayed::PerformableMethod.new(clazz.new, :private_method, []) }.not_to raise_error
|
40
38
|
end
|
41
39
|
|
42
|
-
describe
|
43
|
-
%w
|
40
|
+
describe 'hooks' do
|
41
|
+
%w[before after success].each do |hook|
|
44
42
|
it "delegates #{hook} hook to object" do
|
45
43
|
story = Story.create
|
46
44
|
job = story.delay.tell
|
@@ -50,7 +48,7 @@ describe Delayed::PerformableMethod do
|
|
50
48
|
end
|
51
49
|
end
|
52
50
|
|
53
|
-
%w
|
51
|
+
%w[before after success].each do |hook|
|
54
52
|
it "delegates #{hook} hook to object" do
|
55
53
|
story = Story.create
|
56
54
|
job = story.delay.tell
|
@@ -60,28 +58,28 @@ describe Delayed::PerformableMethod do
|
|
60
58
|
end
|
61
59
|
end
|
62
60
|
|
63
|
-
it
|
61
|
+
it 'delegates enqueue hook to object' do
|
64
62
|
story = Story.create
|
65
63
|
expect(story).to receive(:enqueue).with(an_instance_of(Delayed::Job))
|
66
64
|
story.delay.tell
|
67
65
|
end
|
68
66
|
|
69
|
-
it
|
67
|
+
it 'delegates error hook to object' do
|
70
68
|
story = Story.create
|
71
69
|
expect(story).to receive(:error).with(an_instance_of(Delayed::Job), an_instance_of(RuntimeError))
|
72
70
|
expect(story).to receive(:tell).and_raise(RuntimeError)
|
73
71
|
expect { story.delay.tell.invoke_job }.to raise_error
|
74
72
|
end
|
75
73
|
|
76
|
-
it
|
74
|
+
it 'delegates error hook to object when delay_jobs = false' do
|
77
75
|
story = Story.create
|
78
76
|
expect(story).to receive(:error).with(an_instance_of(Delayed::Job), an_instance_of(RuntimeError))
|
79
77
|
expect(story).to receive(:tell).and_raise(RuntimeError)
|
80
78
|
expect { story.delay.tell.invoke_job }.to raise_error
|
81
79
|
end
|
82
80
|
|
83
|
-
it
|
84
|
-
method = Delayed::PerformableMethod.new(
|
81
|
+
it 'delegates failure hook to object' do
|
82
|
+
method = Delayed::PerformableMethod.new('object', :size, [])
|
85
83
|
expect(method.object).to receive(:failure)
|
86
84
|
method.failure
|
87
85
|
end
|
@@ -95,7 +93,7 @@ describe Delayed::PerformableMethod do
|
|
95
93
|
Delayed::Worker.delay_jobs = true
|
96
94
|
end
|
97
95
|
|
98
|
-
%w
|
96
|
+
%w[before after success].each do |hook|
|
99
97
|
it "delegates #{hook} hook to object" do
|
100
98
|
story = Story.create
|
101
99
|
expect(story).to receive(hook).with(an_instance_of(Delayed::Job))
|
@@ -103,7 +101,7 @@ describe Delayed::PerformableMethod do
|
|
103
101
|
end
|
104
102
|
end
|
105
103
|
|
106
|
-
%w
|
104
|
+
%w[before after success].each do |hook|
|
107
105
|
it "delegates #{hook} hook to object" do
|
108
106
|
story = Story.create
|
109
107
|
expect(story).to receive(hook).with(an_instance_of(Delayed::Job))
|
@@ -111,23 +109,23 @@ describe Delayed::PerformableMethod do
|
|
111
109
|
end
|
112
110
|
end
|
113
111
|
|
114
|
-
it
|
112
|
+
it 'delegates error hook to object' do
|
115
113
|
story = Story.create
|
116
114
|
expect(story).to receive(:error).with(an_instance_of(Delayed::Job), an_instance_of(RuntimeError))
|
117
115
|
expect(story).to receive(:tell).and_raise(RuntimeError)
|
118
116
|
expect { story.delay.tell }.to raise_error
|
119
117
|
end
|
120
118
|
|
121
|
-
it
|
119
|
+
it 'delegates error hook to object when delay_jobs = false' do
|
122
120
|
story = Story.create
|
123
121
|
expect(story).to receive(:error).with(an_instance_of(Delayed::Job), an_instance_of(RuntimeError))
|
124
122
|
expect(story).to receive(:tell).and_raise(RuntimeError)
|
125
123
|
expect { story.delay.tell }.to raise_error
|
126
124
|
end
|
127
125
|
|
128
|
-
it
|
126
|
+
it 'delegates failure hook to object when delay_jobs = false' do
|
129
127
|
Delayed::Worker.delay_jobs = false
|
130
|
-
method = Delayed::PerformableMethod.new(
|
128
|
+
method = Delayed::PerformableMethod.new('object', :size, [])
|
131
129
|
expect(method.object).to receive(:failure)
|
132
130
|
method.failure
|
133
131
|
end
|