delayed_job 2.1.2 → 2.1.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.
- data/README.textile +3 -0
- data/lib/delayed/backend/active_record.rb +22 -14
- data/lib/delayed/backend/base.rb +7 -3
- data/lib/delayed/backend/shared_spec.rb +18 -0
- data/lib/delayed/recipes.rb +1 -1
- data/lib/delayed/worker.rb +2 -1
- data/lib/generators/delayed_job/templates/migration.rb +0 -1
- data/spec/message_sending_spec.rb +27 -0
- metadata +17 -22
data/README.textile
CHANGED
@@ -206,6 +206,8 @@ Delayed::Worker.destroy_failed_jobs = false. The failed jobs will be marked with
|
|
206
206
|
|
207
207
|
By default all jobs are scheduled with priority = 0, which is top priority. You can change this by setting Delayed::Worker.default_priority to something else. Lower numbers have higher priority.
|
208
208
|
|
209
|
+
It is possible to disable delayed jobs for testing purposes. Set Delayed::Worker.delay_jobs = false to execute all jobs realtime.
|
210
|
+
|
209
211
|
Here is an example of changing job parameters in Rails:
|
210
212
|
|
211
213
|
<pre>
|
@@ -214,6 +216,7 @@ Delayed::Worker.destroy_failed_jobs = false
|
|
214
216
|
Delayed::Worker.sleep_delay = 60
|
215
217
|
Delayed::Worker.max_attempts = 3
|
216
218
|
Delayed::Worker.max_run_time = 5.minutes
|
219
|
+
Delayed::Worker.delay_jobs = !Rails.env.test?
|
217
220
|
</pre>
|
218
221
|
|
219
222
|
h3. Cleaning up
|
@@ -16,10 +16,6 @@ module Delayed
|
|
16
16
|
}
|
17
17
|
scope :by_priority, order('priority ASC, run_at ASC')
|
18
18
|
|
19
|
-
scope :locked_by_worker, lambda{|worker_name, max_run_time|
|
20
|
-
where(['locked_by = ? AND locked_at > ?', worker_name, db_time_now - max_run_time])
|
21
|
-
}
|
22
|
-
|
23
19
|
def self.before_fork
|
24
20
|
::ActiveRecord::Base.clear_all_connections!
|
25
21
|
end
|
@@ -33,25 +29,37 @@ module Delayed
|
|
33
29
|
update_all("locked_by = null, locked_at = null", ["locked_by = ?", worker_name])
|
34
30
|
end
|
35
31
|
|
36
|
-
|
32
|
+
# Find a few candidate jobs to run (in case some immediately get locked by others).
|
33
|
+
def self.find_available(worker_name, limit = 5, max_run_time = Worker.max_run_time)
|
37
34
|
scope = self.ready_to_run(worker_name, max_run_time)
|
38
35
|
scope = scope.scoped(:conditions => ['priority >= ?', Worker.min_priority]) if Worker.min_priority
|
39
36
|
scope = scope.scoped(:conditions => ['priority <= ?', Worker.max_priority]) if Worker.max_priority
|
40
|
-
scope.by_priority
|
41
|
-
end
|
42
37
|
|
43
|
-
# Reserve a single job in a single update query. This causes workers to serialize on the
|
44
|
-
# database and avoids contention.
|
45
|
-
def self.reserve(worker, max_run_time = Worker.max_run_time)
|
46
|
-
affected_rows = 0
|
47
38
|
::ActiveRecord::Base.silence do
|
48
|
-
|
39
|
+
scope.by_priority.all(:limit => limit)
|
49
40
|
end
|
41
|
+
end
|
50
42
|
|
43
|
+
# Lock this job for this worker.
|
44
|
+
# Returns true if we have the lock, false otherwise.
|
45
|
+
def lock_exclusively!(max_run_time, worker)
|
46
|
+
now = self.class.db_time_now
|
47
|
+
affected_rows = if locked_by != worker
|
48
|
+
# We don't own this job so we will update the locked_by name and the locked_at
|
49
|
+
self.class.update_all(["locked_at = ?, locked_by = ?", now, worker], ["id = ? and (locked_at is null or locked_at < ?) and (run_at <= ?)", id, (now - max_run_time.to_i), now])
|
50
|
+
else
|
51
|
+
# We already own this job, this may happen if the job queue crashes.
|
52
|
+
# Simply resume and update the locked_at
|
53
|
+
self.class.update_all(["locked_at = ?", now], ["id = ? and locked_by = ?", id, worker])
|
54
|
+
end
|
51
55
|
if affected_rows == 1
|
52
|
-
|
56
|
+
self.locked_at = now
|
57
|
+
self.locked_by = worker
|
58
|
+
self.locked_at_will_change!
|
59
|
+
self.locked_by_will_change!
|
60
|
+
return true
|
53
61
|
else
|
54
|
-
|
62
|
+
return false
|
55
63
|
end
|
56
64
|
end
|
57
65
|
|
data/lib/delayed/backend/base.rb
CHANGED
@@ -23,9 +23,13 @@ module Delayed
|
|
23
23
|
unless options[:payload_object].respond_to?(:perform)
|
24
24
|
raise ArgumentError, 'Cannot enqueue items which do not respond to perform'
|
25
25
|
end
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
|
27
|
+
if Delayed::Worker.delay_jobs
|
28
|
+
self.create(options).tap do |job|
|
29
|
+
job.hook(:enqueue)
|
30
|
+
end
|
31
|
+
else
|
32
|
+
options[:payload_object].perform
|
29
33
|
end
|
30
34
|
end
|
31
35
|
|
@@ -11,6 +11,7 @@ shared_examples_for 'a delayed_job backend' do
|
|
11
11
|
Delayed::Worker.max_priority = nil
|
12
12
|
Delayed::Worker.min_priority = nil
|
13
13
|
Delayed::Worker.default_priority = 99
|
14
|
+
Delayed::Worker.delay_jobs = true
|
14
15
|
SimpleJob.runs = 0
|
15
16
|
described_class.delete_all
|
16
17
|
end
|
@@ -57,6 +58,12 @@ shared_examples_for 'a delayed_job backend' do
|
|
57
58
|
described_class.enqueue SimpleJob.new
|
58
59
|
described_class.count.should == 1
|
59
60
|
end
|
61
|
+
|
62
|
+
it "should not increase count after enqueuing items when delay_jobs is false" do
|
63
|
+
Delayed::Worker.delay_jobs = false
|
64
|
+
described_class.enqueue SimpleJob.new
|
65
|
+
described_class.count.should == 0
|
66
|
+
end
|
60
67
|
|
61
68
|
it "should be able to set priority [DEPRECATED]" do
|
62
69
|
silence_warnings do
|
@@ -155,6 +162,17 @@ shared_examples_for 'a delayed_job backend' do
|
|
155
162
|
described_class.reserve(worker).should be_nil
|
156
163
|
end
|
157
164
|
|
165
|
+
it "should reserve jobs scheduled for the past" do
|
166
|
+
job = create_job :run_at => described_class.db_time_now - 1.minute
|
167
|
+
described_class.reserve(worker).should == job
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should reserve jobs scheduled for the past when time zones are involved" do
|
171
|
+
Time.zone = 'US/Eastern'
|
172
|
+
job = create_job :run_at => described_class.db_time_now - 1.minute.ago.in_time_zone
|
173
|
+
described_class.reserve(worker).should == job
|
174
|
+
end
|
175
|
+
|
158
176
|
it "should not reserve jobs locked by other workers" do
|
159
177
|
job = create_job
|
160
178
|
other_worker = Delayed::Worker.new
|
data/lib/delayed/recipes.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
# If you want to use command line options, for example to start multiple workers,
|
11
11
|
# define a Capistrano variable delayed_job_args:
|
12
12
|
#
|
13
|
-
# set :
|
13
|
+
# set :delayed_job_args, "-n 2"
|
14
14
|
#
|
15
15
|
# If you've got delayed_job workers running on a servers, you can also specify
|
16
16
|
# which servers have delayed_job running and should be restarted after deploy.
|
data/lib/delayed/worker.rb
CHANGED
@@ -6,11 +6,12 @@ require 'logger'
|
|
6
6
|
|
7
7
|
module Delayed
|
8
8
|
class Worker
|
9
|
-
cattr_accessor :min_priority, :max_priority, :max_attempts, :max_run_time, :default_priority, :sleep_delay, :logger
|
9
|
+
cattr_accessor :min_priority, :max_priority, :max_attempts, :max_run_time, :default_priority, :sleep_delay, :logger, :delay_jobs
|
10
10
|
self.sleep_delay = 5
|
11
11
|
self.max_attempts = 25
|
12
12
|
self.max_run_time = 4.hours
|
13
13
|
self.default_priority = 0
|
14
|
+
self.delay_jobs = true
|
14
15
|
|
15
16
|
# By default failed jobs are destroyed after too many attempts. If you want to keep them around
|
16
17
|
# (perhaps to inspect the reason for the failure), set this to false.
|
@@ -85,5 +85,32 @@ describe Delayed::MessageSending do
|
|
85
85
|
job.run_at.should == run_at
|
86
86
|
job.priority.should == 20
|
87
87
|
end
|
88
|
+
|
89
|
+
class FairyTail
|
90
|
+
attr_accessor :happy_ending
|
91
|
+
def tell
|
92
|
+
@happy_ending = true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should not delay the job when delay_jobs is false" do
|
97
|
+
Delayed::Worker.delay_jobs = false
|
98
|
+
fairy_tail = FairyTail.new
|
99
|
+
lambda {
|
100
|
+
lambda {
|
101
|
+
fairy_tail.delay.tell
|
102
|
+
}.should change(fairy_tail, :happy_ending).from(nil).to(true)
|
103
|
+
}.should_not change { Delayed::Job.count }
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should delay the job when delay_jobs is true" do
|
107
|
+
Delayed::Worker.delay_jobs = true
|
108
|
+
fairy_tail = FairyTail.new
|
109
|
+
lambda {
|
110
|
+
lambda {
|
111
|
+
fairy_tail.delay.tell
|
112
|
+
}.should_not change(fairy_tail, :happy_ending)
|
113
|
+
}.should change { Delayed::Job.count }.by(1)
|
114
|
+
end
|
88
115
|
end
|
89
116
|
end
|
metadata
CHANGED
@@ -1,130 +1,125 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delayed_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 15
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 2
|
8
7
|
- 1
|
9
|
-
-
|
10
|
-
version: 2.1.
|
8
|
+
- 3
|
9
|
+
version: 2.1.3
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
12
|
+
- Chris Gaffney
|
13
13
|
- Brandon Keepers
|
14
14
|
- "Tobias L\xC3\xBCtke"
|
15
15
|
autorequire:
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date:
|
19
|
+
date: 2011-01-20 00:00:00 -07:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
23
|
name: daemons
|
24
|
-
prerelease: false
|
25
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
26
25
|
none: false
|
27
26
|
requirements:
|
28
27
|
- - ">="
|
29
28
|
- !ruby/object:Gem::Version
|
30
|
-
hash: 3
|
31
29
|
segments:
|
32
30
|
- 0
|
33
31
|
version: "0"
|
34
32
|
type: :runtime
|
33
|
+
prerelease: false
|
35
34
|
version_requirements: *id001
|
36
35
|
- !ruby/object:Gem::Dependency
|
37
36
|
name: activesupport
|
38
|
-
prerelease: false
|
39
37
|
requirement: &id002 !ruby/object:Gem::Requirement
|
40
38
|
none: false
|
41
39
|
requirements:
|
42
40
|
- - ~>
|
43
41
|
- !ruby/object:Gem::Version
|
44
|
-
hash: 7
|
45
42
|
segments:
|
46
43
|
- 3
|
47
44
|
- 0
|
48
45
|
version: "3.0"
|
49
46
|
type: :runtime
|
47
|
+
prerelease: false
|
50
48
|
version_requirements: *id002
|
51
49
|
- !ruby/object:Gem::Dependency
|
52
50
|
name: rspec
|
53
|
-
prerelease: false
|
54
51
|
requirement: &id003 !ruby/object:Gem::Requirement
|
55
52
|
none: false
|
56
53
|
requirements:
|
57
54
|
- - ~>
|
58
55
|
- !ruby/object:Gem::Version
|
59
|
-
hash: 3
|
60
56
|
segments:
|
61
57
|
- 2
|
62
58
|
- 0
|
63
59
|
version: "2.0"
|
64
60
|
type: :development
|
61
|
+
prerelease: false
|
65
62
|
version_requirements: *id003
|
66
63
|
- !ruby/object:Gem::Dependency
|
67
64
|
name: rake
|
68
|
-
prerelease: false
|
69
65
|
requirement: &id004 !ruby/object:Gem::Requirement
|
70
66
|
none: false
|
71
67
|
requirements:
|
72
68
|
- - ">="
|
73
69
|
- !ruby/object:Gem::Version
|
74
|
-
hash: 3
|
75
70
|
segments:
|
76
71
|
- 0
|
77
72
|
version: "0"
|
78
73
|
type: :development
|
74
|
+
prerelease: false
|
79
75
|
version_requirements: *id004
|
80
76
|
- !ruby/object:Gem::Dependency
|
81
77
|
name: rails
|
82
|
-
prerelease: false
|
83
78
|
requirement: &id005 !ruby/object:Gem::Requirement
|
84
79
|
none: false
|
85
80
|
requirements:
|
86
81
|
- - ~>
|
87
82
|
- !ruby/object:Gem::Version
|
88
|
-
hash: 7
|
89
83
|
segments:
|
90
84
|
- 3
|
91
85
|
- 0
|
92
86
|
version: "3.0"
|
93
87
|
type: :development
|
88
|
+
prerelease: false
|
94
89
|
version_requirements: *id005
|
95
90
|
- !ruby/object:Gem::Dependency
|
96
|
-
name: sqlite3
|
97
|
-
prerelease: false
|
91
|
+
name: sqlite3
|
98
92
|
requirement: &id006 !ruby/object:Gem::Requirement
|
99
93
|
none: false
|
100
94
|
requirements:
|
101
95
|
- - ">="
|
102
96
|
- !ruby/object:Gem::Version
|
103
|
-
hash: 3
|
104
97
|
segments:
|
105
98
|
- 0
|
106
99
|
version: "0"
|
107
100
|
type: :development
|
101
|
+
prerelease: false
|
108
102
|
version_requirements: *id006
|
109
103
|
- !ruby/object:Gem::Dependency
|
110
104
|
name: mysql
|
111
|
-
prerelease: false
|
112
105
|
requirement: &id007 !ruby/object:Gem::Requirement
|
113
106
|
none: false
|
114
107
|
requirements:
|
115
108
|
- - ">="
|
116
109
|
- !ruby/object:Gem::Version
|
117
|
-
hash: 3
|
118
110
|
segments:
|
119
111
|
- 0
|
120
112
|
version: "0"
|
121
113
|
type: :development
|
114
|
+
prerelease: false
|
122
115
|
version_requirements: *id007
|
123
116
|
description: |-
|
124
117
|
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.
|
125
118
|
|
126
119
|
This gem is collectiveidea's fork (http://github.com/collectiveidea/delayed_job).
|
127
|
-
email:
|
120
|
+
email:
|
121
|
+
- chris@collectiveidea.com
|
122
|
+
- brandon@opensoul.org
|
128
123
|
executables: []
|
129
124
|
|
130
125
|
extensions: []
|
@@ -183,7 +178,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
183
178
|
requirements:
|
184
179
|
- - ">="
|
185
180
|
- !ruby/object:Gem::Version
|
186
|
-
hash:
|
181
|
+
hash: -1896469102761102405
|
187
182
|
segments:
|
188
183
|
- 0
|
189
184
|
version: "0"
|
@@ -192,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
192
187
|
requirements:
|
193
188
|
- - ">="
|
194
189
|
- !ruby/object:Gem::Version
|
195
|
-
hash:
|
190
|
+
hash: -1896469102761102405
|
196
191
|
segments:
|
197
192
|
- 0
|
198
193
|
version: "0"
|