delayed_job 4.0.0.beta2 → 4.0.0
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/CHANGELOG.md +6 -0
- data/CONTRIBUTING.md +10 -1
- data/README.md +3 -0
- data/delayed_job.gemspec +1 -1
- data/lib/delayed/backend/base.rb +11 -1
- data/lib/delayed/backend/shared_spec.rb +4 -4
- data/lib/delayed/command.rb +2 -6
- data/lib/delayed/worker.rb +14 -1
- data/spec/lifecycle_spec.rb +1 -1
- data/spec/performable_mailer_spec.rb +2 -2
- data/spec/performable_method_spec.rb +1 -1
- data/spec/worker_spec.rb +29 -1
- metadata +21 -11
- checksums.yaml +0 -15
data/CHANGELOG.md
CHANGED
data/CONTRIBUTING.md
CHANGED
@@ -7,7 +7,16 @@ If you find what looks like a bug:
|
|
7
7
|
if anyone else had the same issue.
|
8
8
|
* Check the "GitHub issue tracker":http://github.com/collectiveidea/delayed_job/issues/
|
9
9
|
to see if anyone else has reported issue.
|
10
|
-
*
|
10
|
+
* Make sure you are using the latest version of delayed_job
|
11
|
+

|
12
|
+
* Make sure you are using the latest backend gem for delayed_job
|
13
|
+
* Active Record 
|
14
|
+
* Mongoid 
|
15
|
+
* If you are still having an issue, create an issue including:
|
16
|
+
* Ruby version
|
17
|
+
* Gemfile.lock contents or at least major gem versions, such as Rails version
|
18
|
+
* Steps to reproduce the issue
|
19
|
+
* Full backtrace for any errors encountered
|
11
20
|
|
12
21
|
If you want to contribute an enhancement or a fix:
|
13
22
|
|
data/README.md
CHANGED
@@ -316,6 +316,8 @@ By default all jobs are scheduled with priority = 0, which is top priority. You
|
|
316
316
|
|
317
317
|
The default behavior is to read 5 jobs from the queue when finding an available job. You can configure this by setting Delayed::Worker.read_ahead.
|
318
318
|
|
319
|
+
By default all jobs will be queued without a named queue. A default named queue can be specified by using Delayed::Worker.default_queue_name.
|
320
|
+
|
319
321
|
It is possible to disable delayed jobs for testing purposes. Set Delayed::Worker.delay_jobs = false to execute all jobs realtime.
|
320
322
|
|
321
323
|
Here is an example of changing job parameters in Rails:
|
@@ -327,6 +329,7 @@ Delayed::Worker.sleep_delay = 60
|
|
327
329
|
Delayed::Worker.max_attempts = 3
|
328
330
|
Delayed::Worker.max_run_time = 5.minutes
|
329
331
|
Delayed::Worker.read_ahead = 10
|
332
|
+
Delayed::Worker.default_queue_name = 'default'
|
330
333
|
Delayed::Worker.delay_jobs = !Rails.env.test?
|
331
334
|
```
|
332
335
|
|
data/delayed_job.gemspec
CHANGED
@@ -13,5 +13,5 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.require_paths = ['lib']
|
14
14
|
spec.summary = 'Database-backed asynchronous priority queue system -- Extracted from Shopify'
|
15
15
|
spec.test_files = Dir.glob('spec/**/*')
|
16
|
-
spec.version = '4.0.0
|
16
|
+
spec.version = '4.0.0'
|
17
17
|
end
|
data/lib/delayed/backend/base.rb
CHANGED
@@ -47,6 +47,10 @@ module Delayed
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
# Allow the backend to attempt recovery from reserve errors
|
51
|
+
def recover_from(error)
|
52
|
+
end
|
53
|
+
|
50
54
|
# Hook method that is called before a new worker is forked
|
51
55
|
def before_fork
|
52
56
|
end
|
@@ -82,7 +86,13 @@ module Delayed
|
|
82
86
|
end
|
83
87
|
|
84
88
|
def payload_object
|
85
|
-
|
89
|
+
if YAML.respond_to?(:unsafe_load)
|
90
|
+
#See https://github.com/dtao/safe_yaml
|
91
|
+
#When the method is there, we need to load our YAML like this...
|
92
|
+
@payload_object ||= YAML.load(self.handler, :safe => false)
|
93
|
+
else
|
94
|
+
@payload_object ||= YAML.load(self.handler)
|
95
|
+
end
|
86
96
|
rescue TypeError, LoadError, NameError, ArgumentError => e
|
87
97
|
raise DeserializationError,
|
88
98
|
"Job failed to load: #{e.message}. Handler: #{handler.inspect}"
|
@@ -399,7 +399,7 @@ shared_examples_for "a delayed_job backend" do
|
|
399
399
|
end
|
400
400
|
|
401
401
|
it "uses the max_retries value on the payload when defined" do
|
402
|
-
@job.payload_object.stub
|
402
|
+
@job.payload_object.stub(:max_attempts).and_return(99)
|
403
403
|
expect(@job.max_attempts).to eq(99)
|
404
404
|
end
|
405
405
|
end
|
@@ -504,8 +504,8 @@ shared_examples_for "a delayed_job backend" do
|
|
504
504
|
|
505
505
|
it "does not fail when the triggered error doesn't have a message" do
|
506
506
|
error_with_nil_message = StandardError.new
|
507
|
-
error_with_nil_message.stub
|
508
|
-
@job.stub
|
507
|
+
error_with_nil_message.stub(:message).and_return nil
|
508
|
+
@job.stub(:invoke_job).and_raise error_with_nil_message
|
509
509
|
expect{worker.run(@job)}.not_to raise_error
|
510
510
|
end
|
511
511
|
end
|
@@ -548,7 +548,7 @@ shared_examples_for "a delayed_job backend" do
|
|
548
548
|
it "does not try to run that hook" do
|
549
549
|
expect {
|
550
550
|
Delayed::Worker.max_attempts.times { worker.reschedule(@job) }
|
551
|
-
}.not_to raise_exception
|
551
|
+
}.not_to raise_exception
|
552
552
|
end
|
553
553
|
end
|
554
554
|
end
|
data/lib/delayed/command.rb
CHANGED
@@ -78,14 +78,10 @@ module Delayed
|
|
78
78
|
process_name = "delayed_job.#{@options[:identifier]}"
|
79
79
|
run_process(process_name, dir)
|
80
80
|
else
|
81
|
-
threads = []
|
82
81
|
worker_count.times do |worker_index|
|
83
|
-
|
84
|
-
|
85
|
-
run_process(process_name, dir)
|
86
|
-
end
|
82
|
+
process_name = worker_count == 1 ? "delayed_job" : "delayed_job.#{worker_index}"
|
83
|
+
run_process(process_name, dir)
|
87
84
|
end
|
88
|
-
threads.each(&:join)
|
89
85
|
end
|
90
86
|
end
|
91
87
|
|
data/lib/delayed/worker.rb
CHANGED
@@ -107,6 +107,7 @@ module Delayed
|
|
107
107
|
|
108
108
|
def initialize(options={})
|
109
109
|
@quiet = options.has_key?(:quiet) ? options[:quiet] : true
|
110
|
+
@failed_reserve_count = 0
|
110
111
|
|
111
112
|
[:min_priority, :max_priority, :sleep_delay, :read_ahead, :queues, :exit_on_complete].each do |option|
|
112
113
|
self.class.send("#{option}=", options[option]) if options.has_key?(option)
|
@@ -262,9 +263,21 @@ module Delayed
|
|
262
263
|
# Run the next job we can get an exclusive lock on.
|
263
264
|
# If no jobs are left we return nil
|
264
265
|
def reserve_and_run_one_job
|
265
|
-
job =
|
266
|
+
job = reserve_job
|
266
267
|
self.class.lifecycle.run_callbacks(:perform, self, job){ run(job) } if job
|
267
268
|
end
|
269
|
+
|
270
|
+
def reserve_job
|
271
|
+
job = Delayed::Job.reserve(self)
|
272
|
+
@failed_reserve_count = 0
|
273
|
+
job
|
274
|
+
rescue Exception => error
|
275
|
+
say "Error while reserving job: #{error}"
|
276
|
+
Delayed::Job.recover_from(error)
|
277
|
+
@failed_reserve_count += 1
|
278
|
+
raise FatalBackendError if @failed_reserve_count >= 10
|
279
|
+
nil
|
280
|
+
end
|
268
281
|
end
|
269
282
|
|
270
283
|
end
|
data/spec/lifecycle_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe Delayed::Lifecycle do
|
|
4
4
|
let(:lifecycle) { Delayed::Lifecycle.new }
|
5
5
|
let(:callback) { lambda {|*args|} }
|
6
6
|
let(:arguments) { [1] }
|
7
|
-
let(:behavior) {
|
7
|
+
let(:behavior) { double(Object, :before! => nil, :after! => nil, :inside! => nil) }
|
8
8
|
let(:wrapped_block) { Proc.new { behavior.inside! } }
|
9
9
|
|
10
10
|
describe "before callbacks" do
|
@@ -30,8 +30,8 @@ describe ActionMailer::Base do
|
|
30
30
|
describe Delayed::PerformableMailer do
|
31
31
|
describe "perform" do
|
32
32
|
it "calls the method and #deliver on the mailer" do
|
33
|
-
email =
|
34
|
-
mailer_class =
|
33
|
+
email = double('email', :deliver => true)
|
34
|
+
mailer_class = double('MailerClass', :signup => email)
|
35
35
|
mailer = Delayed::PerformableMailer.new(mailer_class, :signup, ['john@example.com'])
|
36
36
|
|
37
37
|
mailer_class.should_receive(:signup).with('john@example.com')
|
data/spec/worker_spec.rb
CHANGED
@@ -24,7 +24,7 @@ describe Delayed::Worker do
|
|
24
24
|
describe "job_say" do
|
25
25
|
before do
|
26
26
|
@worker = Delayed::Worker.new
|
27
|
-
@job =
|
27
|
+
@job = double('job', :id => 123, :name => 'ExampleJob')
|
28
28
|
end
|
29
29
|
|
30
30
|
it "logs with job name and id" do
|
@@ -71,4 +71,32 @@ describe Delayed::Worker do
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
74
|
+
|
75
|
+
context "worker job reservation" do
|
76
|
+
before do
|
77
|
+
Delayed::Worker.exit_on_complete = true
|
78
|
+
end
|
79
|
+
|
80
|
+
after do
|
81
|
+
Delayed::Worker.exit_on_complete = false
|
82
|
+
end
|
83
|
+
|
84
|
+
it "handles error during job reservation" do
|
85
|
+
Delayed::Job.should_receive(:reserve).and_raise(Exception)
|
86
|
+
Delayed::Worker.new.work_off
|
87
|
+
end
|
88
|
+
|
89
|
+
it "gives up after 10 backend failures" do
|
90
|
+
Delayed::Job.stub(:reserve).and_raise(Exception)
|
91
|
+
worker = Delayed::Worker.new
|
92
|
+
9.times { worker.work_off }
|
93
|
+
expect(lambda { worker.work_off }).to raise_exception
|
94
|
+
end
|
95
|
+
|
96
|
+
it "allows the backend to attempt recovery from reservation errors" do
|
97
|
+
Delayed::Job.should_receive(:reserve).and_raise(Exception)
|
98
|
+
Delayed::Job.should_receive(:recover_from).with(instance_of(Exception))
|
99
|
+
Delayed::Worker.new.work_off
|
100
|
+
end
|
101
|
+
end
|
74
102
|
end
|
metadata
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delayed_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.0
|
4
|
+
version: 4.0.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Brandon Keepers
|
@@ -15,12 +16,12 @@ authors:
|
|
15
16
|
autorequire:
|
16
17
|
bindir: bin
|
17
18
|
cert_chain: []
|
18
|
-
date: 2013-
|
19
|
+
date: 2013-07-30 00:00:00.000000000 Z
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
|
-
prerelease: false
|
22
22
|
name: activesupport
|
23
|
-
|
23
|
+
requirement: !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
24
25
|
requirements:
|
25
26
|
- - ! '>='
|
26
27
|
- !ruby/object:Gem::Version
|
@@ -28,7 +29,10 @@ dependencies:
|
|
28
29
|
- - <
|
29
30
|
- !ruby/object:Gem::Version
|
30
31
|
version: '4.1'
|
31
|
-
|
32
|
+
type: :runtime
|
33
|
+
prerelease: false
|
34
|
+
version_requirements: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
32
36
|
requirements:
|
33
37
|
- - ! '>='
|
34
38
|
- !ruby/object:Gem::Version
|
@@ -36,7 +40,6 @@ dependencies:
|
|
36
40
|
- - <
|
37
41
|
- !ruby/object:Gem::Version
|
38
42
|
version: '4.1'
|
39
|
-
type: :runtime
|
40
43
|
description: Delayed_job (or DJ) encapsulates the common pattern of asynchronously
|
41
44
|
executing longer tasks in the background. It is a direct extraction from Shopify
|
42
45
|
where the job table is responsible for a multitude of core tasks.
|
@@ -98,26 +101,33 @@ files:
|
|
98
101
|
homepage: http://github.com/collectiveidea/delayed_job
|
99
102
|
licenses:
|
100
103
|
- MIT
|
101
|
-
metadata: {}
|
102
104
|
post_install_message:
|
103
105
|
rdoc_options: []
|
104
106
|
require_paths:
|
105
107
|
- lib
|
106
108
|
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
107
110
|
requirements:
|
108
111
|
- - ! '>='
|
109
112
|
- !ruby/object:Gem::Version
|
110
113
|
version: '0'
|
114
|
+
segments:
|
115
|
+
- 0
|
116
|
+
hash: 3979399263094595498
|
111
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
112
119
|
requirements:
|
113
|
-
- - ! '
|
120
|
+
- - ! '>='
|
114
121
|
- !ruby/object:Gem::Version
|
115
|
-
version:
|
122
|
+
version: '0'
|
123
|
+
segments:
|
124
|
+
- 0
|
125
|
+
hash: 3979399263094595498
|
116
126
|
requirements: []
|
117
127
|
rubyforge_project:
|
118
|
-
rubygems_version:
|
128
|
+
rubygems_version: 1.8.23
|
119
129
|
signing_key:
|
120
|
-
specification_version:
|
130
|
+
specification_version: 3
|
121
131
|
summary: Database-backed asynchronous priority queue system -- Extracted from Shopify
|
122
132
|
test_files:
|
123
133
|
- spec/autoloaded/clazz.rb
|
checksums.yaml
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
---
|
2
|
-
!binary "U0hBMQ==":
|
3
|
-
metadata.gz: !binary |-
|
4
|
-
MTQxN2VkZDVhM2YxY2RhNzE0NzRiN2ZlMDE0ZmQ3Y2I3ZjM5ODkyMA==
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NjI3N2EyYTkzY2E2M2YyNmE2OWYxNTVhOWZkNWI5ZGViZWEzYjIzNQ==
|
7
|
-
!binary "U0hBNTEy":
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
MjhjOGJkN2YxNGM0NzI0ZDIxOTE0ZGVjNTk0OGZhZWQxZmY4YTkxYTczNWRk
|
10
|
-
ZWIxNTEzYWE4Mzc4OGE0Mjc2NzhhMDQ0NjdiZGVjMDc1YzEyMDUyOTFmYmRl
|
11
|
-
OTdmNzYyZDQ4YzJjZWVlOGUzNjczY2VlOTczYTc5Mjk1ZjhjZTE=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MDcxN2FkZDMxYWVhOTI2NjBmN2FmNzgyN2I0MTZkMmM3YmNjZWM4NTk2MzVl
|
14
|
-
ZDA2ZWQ1ZWE4YTE3OGI0ZDlmMTNjMGQ0ZDgyNTllNWM1OTczNzQxNWY3ZTFk
|
15
|
-
NjFkM2ZjMGEzOGYyMTQzNjNhMjg5ODRjNGEzNTExNGM2YjJiZGE=
|