delayed_job 3.0.1 → 3.0.2
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/MIT-LICENSE +1 -1
- data/README.textile +6 -3
- data/contrib/delayed_job.monitrc +1 -1
- data/contrib/delayed_job_multiple.monitrc +3 -3
- data/lib/delayed/backend/base.rb +2 -2
- data/lib/delayed/backend/shared_spec.rb +34 -5
- data/lib/delayed/command.rb +4 -1
- data/lib/delayed/deserialization_error.rb +1 -1
- data/lib/delayed/lifecycle.rb +24 -24
- data/lib/delayed/performable_method.rb +4 -0
- data/lib/delayed/plugin.rb +1 -1
- data/lib/delayed/plugins/clear_locks.rb +3 -3
- data/lib/delayed/psych_ext.rb +1 -1
- data/lib/delayed/recipes.rb +4 -4
- data/lib/delayed/serialization/active_record.rb +1 -1
- data/lib/delayed/worker.rb +25 -9
- data/spec/autoloaded/clazz.rb +1 -1
- data/spec/autoloaded/instance_clazz.rb +1 -1
- data/spec/autoloaded/instance_struct.rb +1 -1
- data/spec/autoloaded/struct.rb +1 -1
- data/spec/delayed/backend/test.rb +20 -20
- data/spec/fixtures/bad_alias.yml +1 -1
- data/spec/lifecycle_spec.rb +1 -1
- data/spec/message_sending_spec.rb +3 -3
- data/spec/performable_method_spec.rb +9 -9
- data/spec/spec_helper.rb +11 -3
- data/spec/test_backend_spec.rb +2 -2
- metadata +17 -17
data/MIT-LICENSE
CHANGED
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOa AND
|
|
17
17
|
NONINFRINGEMENT. IN NO EVENT SaALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
CHANGED
@@ -37,7 +37,7 @@ Run @bundle install@ to install the backend and delayed_job gems.
|
|
37
37
|
The Active Record backend requires a jobs table. You can create that table by running the following command:
|
38
38
|
|
39
39
|
<pre>
|
40
|
-
$
|
40
|
+
$ rails generate delayed_job:active_record
|
41
41
|
$ rake db:migrate
|
42
42
|
</pre>
|
43
43
|
|
@@ -48,7 +48,7 @@ Delayed Job 3.0.0 introduces a new column to the delayed_jobs table.
|
|
48
48
|
If you're upgrading from Delayed Job 2.x, run the upgrade generator to create a migration to add the column.
|
49
49
|
|
50
50
|
<pre>
|
51
|
-
$
|
51
|
+
$ rails generate delayed_job:upgrade
|
52
52
|
$ rake db:migrate
|
53
53
|
</pre>
|
54
54
|
|
@@ -142,7 +142,7 @@ h2. Running Jobs
|
|
142
142
|
|
143
143
|
@script/delayed_job@ can be used to manage a background process which will start working off jobs.
|
144
144
|
|
145
|
-
To do so, add @gem "daemons"@ to your @Gemfile@ and make sure you've run `
|
145
|
+
To do so, add @gem "daemons"@ to your @Gemfile@ and make sure you've run `rails generate delayed_job`.
|
146
146
|
|
147
147
|
You can then do the following:
|
148
148
|
|
@@ -252,6 +252,8 @@ Delayed::Worker.destroy_failed_jobs = false. The failed jobs will be marked with
|
|
252
252
|
|
253
253
|
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.
|
254
254
|
|
255
|
+
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.
|
256
|
+
|
255
257
|
It is possible to disable delayed jobs for testing purposes. Set Delayed::Worker.delay_jobs = false to execute all jobs realtime.
|
256
258
|
|
257
259
|
Here is an example of changing job parameters in Rails:
|
@@ -262,6 +264,7 @@ Delayed::Worker.destroy_failed_jobs = false
|
|
262
264
|
Delayed::Worker.sleep_delay = 60
|
263
265
|
Delayed::Worker.max_attempts = 3
|
264
266
|
Delayed::Worker.max_run_time = 5.minutes
|
267
|
+
Delayed::Worker.read_ahead = 10
|
265
268
|
Delayed::Worker.delay_jobs = !Rails.env.test?
|
266
269
|
</pre>
|
267
270
|
|
data/contrib/delayed_job.monitrc
CHANGED
@@ -11,4 +11,4 @@
|
|
11
11
|
check process delayed_job
|
12
12
|
with pidfile /var/www/apps/{app_name}/shared/pids/delayed_job.pid
|
13
13
|
start program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job start"
|
14
|
-
stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job stop"
|
14
|
+
stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job stop"
|
@@ -11,13 +11,13 @@ check process delayed_job_0
|
|
11
11
|
with pidfile /var/www/apps/{app_name}/shared/pids/delayed_job.0.pid
|
12
12
|
start program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job start -i 0"
|
13
13
|
stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job stop -i 0"
|
14
|
-
|
14
|
+
|
15
15
|
check process delayed_job_1
|
16
16
|
with pidfile /var/www/apps/{app_name}/shared/pids/delayed_job.1.pid
|
17
17
|
start program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job start -i 1"
|
18
18
|
stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job stop -i 1"
|
19
|
-
|
19
|
+
|
20
20
|
check process delayed_job_2
|
21
21
|
with pidfile /var/www/apps/{app_name}/shared/pids/delayed_job.2.pid
|
22
22
|
start program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job start -i 2"
|
23
|
-
stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job stop -i 2"
|
23
|
+
stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job stop -i 2"
|
data/lib/delayed/backend/base.rb
CHANGED
@@ -41,7 +41,7 @@ module Delayed
|
|
41
41
|
def reserve(worker, max_run_time = Worker.max_run_time)
|
42
42
|
# We get up to 5 jobs from the db. In case we cannot get exclusive access to a job we try the next.
|
43
43
|
# this leads to a more even distribution of jobs across the worker processes
|
44
|
-
find_available(worker.name,
|
44
|
+
find_available(worker.name, worker.read_ahead, max_run_time).detect do |job|
|
45
45
|
job.lock_exclusively!(max_run_time, worker.name)
|
46
46
|
end
|
47
47
|
end
|
@@ -61,7 +61,7 @@ module Delayed
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def failed?
|
64
|
-
failed_at
|
64
|
+
!!failed_at
|
65
65
|
end
|
66
66
|
alias_method :failed, :failed?
|
67
67
|
|
@@ -279,6 +279,27 @@ shared_examples_for 'a delayed_job backend' do
|
|
279
279
|
end
|
280
280
|
end
|
281
281
|
|
282
|
+
context "worker read-ahead" do
|
283
|
+
before do
|
284
|
+
@read_ahead = Delayed::Worker.read_ahead
|
285
|
+
end
|
286
|
+
|
287
|
+
after do
|
288
|
+
Delayed::Worker.read_ahead = @read_ahead
|
289
|
+
end
|
290
|
+
|
291
|
+
it "should read five jobs" do
|
292
|
+
described_class.should_receive(:find_available).with(anything, 5, anything).and_return([])
|
293
|
+
described_class.reserve(worker)
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should read a configurable number of jobs" do
|
297
|
+
Delayed::Worker.read_ahead = 15
|
298
|
+
described_class.should_receive(:find_available).with(anything, Delayed::Worker.read_ahead, anything).and_return([])
|
299
|
+
described_class.reserve(worker)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
282
303
|
context "clear_locks!" do
|
283
304
|
before do
|
284
305
|
@job = create_job(:locked_by => 'worker1', :locked_at => described_class.db_time_now)
|
@@ -394,6 +415,14 @@ shared_examples_for 'a delayed_job backend' do
|
|
394
415
|
job.reload.payload_object.object.text.should == 'goodbye'
|
395
416
|
end
|
396
417
|
|
418
|
+
it "should raise error ArgumentError the record is not persisted" do
|
419
|
+
story = Story.new(:text => 'hello')
|
420
|
+
lambda {
|
421
|
+
story.delay.tell
|
422
|
+
}.should raise_error(ArgumentError, "Jobs cannot be created for records before they've been persisted")
|
423
|
+
|
424
|
+
end
|
425
|
+
|
397
426
|
it "should raise deserialization error for destroyed records" do
|
398
427
|
story = Story.create(:text => 'hello')
|
399
428
|
job = story.delay.tell
|
@@ -430,7 +459,7 @@ shared_examples_for 'a delayed_job backend' do
|
|
430
459
|
job = described_class.create! :handler => "--- !ruby/object:JobThatDoesNotExist {}"
|
431
460
|
worker.work_off
|
432
461
|
job.reload
|
433
|
-
job.
|
462
|
+
job.should be_failed
|
434
463
|
end
|
435
464
|
end
|
436
465
|
end
|
@@ -451,7 +480,7 @@ shared_examples_for 'a delayed_job backend' do
|
|
451
480
|
@job.reload
|
452
481
|
@job.last_error.should =~ /did not work/
|
453
482
|
@job.attempts.should == 1
|
454
|
-
@job.
|
483
|
+
@job.should be_failed
|
455
484
|
end
|
456
485
|
|
457
486
|
it "should re-schedule jobs after failing" do
|
@@ -551,14 +580,14 @@ shared_examples_for 'a delayed_job backend' do
|
|
551
580
|
it_should_behave_like "any failure more than Worker.max_attempts times"
|
552
581
|
|
553
582
|
it "should be failed if it failed more than Worker.max_attempts times" do
|
554
|
-
@job.reload.
|
583
|
+
@job.reload.should_not be_failed
|
555
584
|
Delayed::Worker.max_attempts.times { worker.reschedule(@job) }
|
556
|
-
@job.reload.
|
585
|
+
@job.reload.should be_failed
|
557
586
|
end
|
558
587
|
|
559
588
|
it "should not be failed if it failed fewer than Worker.max_attempts times" do
|
560
589
|
(Delayed::Worker.max_attempts - 1).times { worker.reschedule(@job) }
|
561
|
-
@job.reload.
|
590
|
+
@job.reload.should_not be_failed
|
562
591
|
end
|
563
592
|
end
|
564
593
|
end
|
data/lib/delayed/command.rb
CHANGED
@@ -49,6 +49,9 @@ module Delayed
|
|
49
49
|
opts.on('--sleep-delay N', "Amount of time to sleep when no jobs are found") do |n|
|
50
50
|
@options[:sleep_delay] = n
|
51
51
|
end
|
52
|
+
opts.on('--read-ahead N', "Number of jobs from the queue to consider") do |n|
|
53
|
+
@options[:read_ahead] = n
|
54
|
+
end
|
52
55
|
opts.on('-p', '--prefix NAME', "String to be prefixed to worker process names") do |prefix|
|
53
56
|
@options[:prefix] = prefix
|
54
57
|
end
|
@@ -91,7 +94,7 @@ module Delayed
|
|
91
94
|
Dir.chdir(Rails.root)
|
92
95
|
|
93
96
|
Delayed::Worker.after_fork
|
94
|
-
Delayed::Worker.logger
|
97
|
+
Delayed::Worker.logger ||= Logger.new(File.join(Rails.root, 'log', 'delayed_job.log'))
|
95
98
|
|
96
99
|
worker = Delayed::Worker.new(@options)
|
97
100
|
worker.name_prefix = "#{worker_name} "
|
data/lib/delayed/lifecycle.rb
CHANGED
@@ -1,73 +1,73 @@
|
|
1
1
|
module Delayed
|
2
2
|
class InvalidCallback < Exception; end
|
3
|
-
|
3
|
+
|
4
4
|
class Lifecycle
|
5
5
|
EVENTS = {
|
6
|
-
:enqueue
|
7
|
-
:execute
|
8
|
-
:loop
|
9
|
-
:perform
|
10
|
-
:error
|
11
|
-
:failure
|
6
|
+
:enqueue => [:job],
|
7
|
+
:execute => [:worker],
|
8
|
+
:loop => [:worker],
|
9
|
+
:perform => [:worker, :job],
|
10
|
+
:error => [:worker, :job],
|
11
|
+
:failure => [:worker, :job],
|
12
12
|
:invoke_job => [:job]
|
13
13
|
}
|
14
|
-
|
14
|
+
|
15
15
|
def initialize
|
16
16
|
@callbacks = EVENTS.keys.inject({}) { |hash, e| hash[e] = Callback.new; hash }
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def before(event, &block)
|
20
20
|
add(:before, event, &block)
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def after(event, &block)
|
24
24
|
add(:after, event, &block)
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def around(event, &block)
|
28
28
|
add(:around, event, &block)
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def run_callbacks(event, *args, &block)
|
32
32
|
missing_callback(event) unless @callbacks.has_key?(event)
|
33
|
-
|
33
|
+
|
34
34
|
unless EVENTS[event].size == args.size
|
35
35
|
raise ArgumentError, "Callback #{event} expects #{EVENTS[event].size} parameter(s): #{EVENTS[event].join(', ')}"
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
@callbacks[event].execute(*args, &block)
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
private
|
42
|
-
|
42
|
+
|
43
43
|
def add(type, event, &block)
|
44
44
|
missing_callback(event) unless @callbacks.has_key?(event)
|
45
45
|
|
46
46
|
@callbacks[event].add(type, &block)
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
def missing_callback(event)
|
50
50
|
raise InvalidCallback, "Unknown callback event: #{event}"
|
51
51
|
end
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
class Callback
|
55
55
|
def initialize
|
56
56
|
@before = []
|
57
57
|
@after = []
|
58
|
-
|
58
|
+
|
59
59
|
# Identity proc. Avoids special cases when there is no existing around chain.
|
60
60
|
@around = lambda { |*args, &block| block.call(*args) }
|
61
61
|
end
|
62
|
-
|
63
|
-
def execute(*args, &block)
|
62
|
+
|
63
|
+
def execute(*args, &block)
|
64
64
|
@before.each { |c| c.call(*args) }
|
65
65
|
result = @around.call(*args, &block)
|
66
66
|
@after.each { |c| c.call(*args) }
|
67
67
|
result
|
68
68
|
end
|
69
|
-
|
70
|
-
def add(type, &callback)
|
69
|
+
|
70
|
+
def add(type, &callback)
|
71
71
|
case type
|
72
72
|
when :before
|
73
73
|
@before << callback
|
@@ -81,4 +81,4 @@ module Delayed
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
84
|
-
end
|
84
|
+
end
|
@@ -9,6 +9,10 @@ module Delayed
|
|
9
9
|
def initialize(object, method_name, args)
|
10
10
|
raise NoMethodError, "undefined method `#{method_name}' for #{object.inspect}" unless object.respond_to?(method_name, true)
|
11
11
|
|
12
|
+
if defined?(ActiveRecord) && object.kind_of?(ActiveRecord::Base)
|
13
|
+
raise(ArgumentError, 'Jobs cannot be created for records before they\'ve been persisted') if object.attributes[object.class.primary_key].nil?
|
14
|
+
end
|
15
|
+
|
12
16
|
self.object = object
|
13
17
|
self.args = args
|
14
18
|
self.method_name = method_name.to_sym
|
data/lib/delayed/plugin.rb
CHANGED
data/lib/delayed/psych_ext.rb
CHANGED
data/lib/delayed/recipes.rb
CHANGED
@@ -23,15 +23,15 @@ Capistrano::Configuration.instance.load do
|
|
23
23
|
def rails_env
|
24
24
|
fetch(:rails_env, false) ? "RAILS_ENV=#{fetch(:rails_env)}" : ''
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def args
|
28
28
|
fetch(:delayed_job_args, "")
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def roles
|
32
32
|
fetch(:delayed_job_server_role, :app)
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
desc "Stop the delayed_job process"
|
36
36
|
task :stop, :roles => lambda { roles } do
|
37
37
|
run "cd #{current_path};#{rails_env} script/delayed_job stop"
|
@@ -47,4 +47,4 @@ Capistrano::Configuration.instance.load do
|
|
47
47
|
run "cd #{current_path};#{rails_env} script/delayed_job restart #{args}"
|
48
48
|
end
|
49
49
|
end
|
50
|
-
end
|
50
|
+
end
|
data/lib/delayed/worker.rb
CHANGED
@@ -4,16 +4,31 @@ require 'active_support/core_ext/class/attribute_accessors'
|
|
4
4
|
require 'active_support/core_ext/kernel'
|
5
5
|
require 'active_support/core_ext/enumerable'
|
6
6
|
require 'logger'
|
7
|
+
require 'benchmark'
|
7
8
|
|
8
9
|
module Delayed
|
9
10
|
class Worker
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
DEFAULT_SLEEP_DELAY = 5
|
12
|
+
DEFAULT_MAX_ATTEMPTS = 25
|
13
|
+
DEFAULT_MAX_RUN_TIME = 4.hours
|
14
|
+
DEFAULT_DEFAULT_PRIORITY = 0
|
15
|
+
DEFAULT_DELAY_JOBS = true
|
16
|
+
DEFAULT_QUEUES = []
|
17
|
+
DEFAULT_READ_AHEAD = 5
|
18
|
+
|
19
|
+
cattr_accessor :min_priority, :max_priority, :max_attempts, :max_run_time, :default_priority, :sleep_delay, :logger, :delay_jobs, :queues, :read_ahead
|
20
|
+
|
21
|
+
def self.reset
|
22
|
+
self.sleep_delay = DEFAULT_SLEEP_DELAY
|
23
|
+
self.max_attempts = DEFAULT_MAX_ATTEMPTS
|
24
|
+
self.max_run_time = DEFAULT_MAX_RUN_TIME
|
25
|
+
self.default_priority = DEFAULT_DEFAULT_PRIORITY
|
26
|
+
self.delay_jobs = DEFAULT_DELAY_JOBS
|
27
|
+
self.queues = DEFAULT_QUEUES
|
28
|
+
self.read_ahead = DEFAULT_READ_AHEAD
|
29
|
+
end
|
30
|
+
|
31
|
+
reset
|
17
32
|
|
18
33
|
# Add or remove plugins in this list before the worker is instantiated
|
19
34
|
cattr_accessor :plugins
|
@@ -81,8 +96,9 @@ module Delayed
|
|
81
96
|
@quiet = options.has_key?(:quiet) ? options[:quiet] : true
|
82
97
|
self.class.min_priority = options[:min_priority] if options.has_key?(:min_priority)
|
83
98
|
self.class.max_priority = options[:max_priority] if options.has_key?(:max_priority)
|
84
|
-
self.class.sleep_delay
|
85
|
-
self.class.
|
99
|
+
self.class.sleep_delay = options[:sleep_delay] if options.has_key?(:sleep_delay)
|
100
|
+
self.class.read_ahead = options[:read_ahead] if options.has_key?(:read_ahead)
|
101
|
+
self.class.queues = options[:queues] if options.has_key?(:queues)
|
86
102
|
|
87
103
|
self.plugins.each { |klass| klass.new }
|
88
104
|
end
|
data/spec/autoloaded/clazz.rb
CHANGED
data/spec/autoloaded/struct.rb
CHANGED
@@ -15,55 +15,55 @@ module Delayed
|
|
15
15
|
attr_accessor :locked_by
|
16
16
|
attr_accessor :failed_at
|
17
17
|
attr_accessor :queue
|
18
|
-
|
18
|
+
|
19
19
|
include Delayed::Backend::Base
|
20
20
|
|
21
21
|
cattr_accessor :id
|
22
22
|
self.id = 0
|
23
|
-
|
23
|
+
|
24
24
|
def initialize(hash = {})
|
25
25
|
self.attempts = 0
|
26
26
|
self.priority = 0
|
27
27
|
self.id = (self.class.id += 1)
|
28
28
|
hash.each{|k,v| send(:"#{k}=", v)}
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
@jobs = []
|
32
32
|
def self.all
|
33
33
|
@jobs
|
34
34
|
end
|
35
|
-
|
36
|
-
def self.count
|
35
|
+
|
36
|
+
def self.count
|
37
37
|
all.size
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
def self.delete_all
|
41
41
|
all.clear
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def self.create(attrs = {})
|
45
45
|
new(attrs).tap do |o|
|
46
46
|
o.save
|
47
47
|
end
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
def self.create!(*args); create(*args); end
|
51
|
-
|
51
|
+
|
52
52
|
def self.clear_locks!(worker_name)
|
53
53
|
all.select{|j| j.locked_by == worker_name}.each {|j| j.locked_by = nil; j.locked_at = nil}
|
54
54
|
end
|
55
55
|
|
56
56
|
# Find a few candidate jobs to run (in case some immediately get locked by others).
|
57
57
|
def self.find_available(worker_name, limit = 5, max_run_time = Worker.max_run_time)
|
58
|
-
jobs = all.select do |j|
|
59
|
-
j.run_at <= db_time_now &&
|
58
|
+
jobs = all.select do |j|
|
59
|
+
j.run_at <= db_time_now &&
|
60
60
|
(j.locked_at.nil? || j.locked_at < db_time_now - max_run_time || j.locked_by == worker_name) &&
|
61
|
-
j.
|
61
|
+
!j.failed?
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
jobs = jobs.select{|j| Worker.queues.include?(j.queue)} if Worker.queues.any?
|
65
65
|
jobs = jobs.select{|j| j.priority >= Worker.min_priority} if Worker.min_priority
|
66
|
-
jobs = jobs.select{|j| j.priority <= Worker.max_priority} if Worker.max_priority
|
66
|
+
jobs = jobs.select{|j| j.priority <= Worker.max_priority} if Worker.max_priority
|
67
67
|
jobs.sort_by{|j| [j.priority, j.run_at]}[0..limit-1]
|
68
68
|
end
|
69
69
|
|
@@ -83,25 +83,25 @@ module Delayed
|
|
83
83
|
def self.db_time_now
|
84
84
|
Time.current
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
def update_attributes(attrs = {})
|
88
88
|
attrs.each{|k,v| send(:"#{k}=", v)}
|
89
89
|
save
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
def destroy
|
93
93
|
self.class.all.delete(self)
|
94
94
|
end
|
95
|
-
|
95
|
+
|
96
96
|
def save
|
97
97
|
self.run_at ||= Time.current
|
98
|
-
|
98
|
+
|
99
99
|
self.class.all << self unless self.class.all.include?(self)
|
100
100
|
true
|
101
101
|
end
|
102
|
-
|
102
|
+
|
103
103
|
def save!; save; end
|
104
|
-
|
104
|
+
|
105
105
|
def reload
|
106
106
|
reset
|
107
107
|
self
|
data/spec/fixtures/bad_alias.yml
CHANGED
@@ -1 +1 @@
|
|
1
|
-
foo: *bar
|
1
|
+
foo: *bar
|
data/spec/lifecycle_spec.rb
CHANGED
@@ -13,7 +13,7 @@ describe Delayed::MessageSending do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should create a PerformableMethod" do
|
16
|
-
story = Story.
|
16
|
+
story = Story.create
|
17
17
|
lambda {
|
18
18
|
job = story.tell!(1)
|
19
19
|
job.payload_object.class.should == Delayed::PerformableMethod
|
@@ -89,7 +89,7 @@ describe Delayed::MessageSending do
|
|
89
89
|
job.run_at.should == run_at
|
90
90
|
job.priority.should == 20
|
91
91
|
end
|
92
|
-
|
92
|
+
|
93
93
|
it "should not delay the job when delay_jobs is false" do
|
94
94
|
Delayed::Worker.delay_jobs = false
|
95
95
|
fairy_tail = FairyTail.new
|
@@ -99,7 +99,7 @@ describe Delayed::MessageSending do
|
|
99
99
|
}.should change(fairy_tail, :happy_ending).from(nil).to(true)
|
100
100
|
}.should_not change { Delayed::Job.count }
|
101
101
|
end
|
102
|
-
|
102
|
+
|
103
103
|
it "should delay the job when delay_jobs is true" do
|
104
104
|
Delayed::Worker.delay_jobs = true
|
105
105
|
fairy_tail = FairyTail.new
|
@@ -42,31 +42,31 @@ describe Delayed::PerformableMethod do
|
|
42
42
|
describe "hooks" do
|
43
43
|
%w(enqueue before after success).each do |hook|
|
44
44
|
it "should delegate #{hook} hook to object" do
|
45
|
-
story = Story.
|
45
|
+
story = Story.create
|
46
46
|
story.should_receive(hook).with(an_instance_of(Delayed::Job))
|
47
47
|
story.delay.tell.invoke_job
|
48
48
|
end
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
%w(before after success).each do |hook|
|
52
52
|
it "should delegate #{hook} hook to object when delay_jobs = false" do
|
53
53
|
Delayed::Worker.delay_jobs = false
|
54
|
-
story = Story.
|
54
|
+
story = Story.create
|
55
55
|
story.should_receive(hook).with(an_instance_of(Delayed::Job))
|
56
56
|
story.delay.tell
|
57
57
|
end
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
it "should delegate error hook to object" do
|
61
|
-
story = Story.
|
61
|
+
story = Story.create
|
62
62
|
story.should_receive(:error).with(an_instance_of(Delayed::Job), an_instance_of(RuntimeError))
|
63
63
|
story.should_receive(:tell).and_raise(RuntimeError)
|
64
64
|
lambda { story.delay.tell.invoke_job }.should raise_error
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
it "should delegate error hook to object when delay_jobs = false" do
|
68
68
|
Delayed::Worker.delay_jobs = false
|
69
|
-
story = Story.
|
69
|
+
story = Story.create
|
70
70
|
story.should_receive(:error).with(an_instance_of(Delayed::Job), an_instance_of(RuntimeError))
|
71
71
|
story.should_receive(:tell).and_raise(RuntimeError)
|
72
72
|
lambda { story.delay.tell }.should raise_error
|
@@ -77,13 +77,13 @@ describe Delayed::PerformableMethod do
|
|
77
77
|
method.object.should_receive(:failure)
|
78
78
|
method.failure
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
it "should delegate failure hook to object when delay_jobs = false" do
|
82
82
|
Delayed::Worker.delay_jobs = false
|
83
83
|
method = Delayed::PerformableMethod.new("object", :size, [])
|
84
84
|
method.object.should_receive(:failure)
|
85
85
|
method.failure
|
86
86
|
end
|
87
|
-
|
87
|
+
|
88
88
|
end
|
89
89
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
unless ENV['CI']
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start
|
4
|
+
end
|
2
5
|
|
3
6
|
require 'bundler/setup'
|
4
7
|
require 'logger'
|
5
8
|
|
6
|
-
require 'rails'
|
7
9
|
require 'action_mailer'
|
8
10
|
require 'active_support/dependencies'
|
9
11
|
require 'active_record'
|
@@ -36,10 +38,16 @@ ActiveRecord::Schema.define do
|
|
36
38
|
end
|
37
39
|
|
38
40
|
class Story < ActiveRecord::Base
|
39
|
-
|
41
|
+
self.primary_key = 'story_id'
|
40
42
|
def tell; text; end
|
41
43
|
def whatever(n, _); tell*n; end
|
42
44
|
default_scope where(:scoped => true)
|
43
45
|
|
44
46
|
handle_asynchronously :whatever
|
45
47
|
end
|
48
|
+
|
49
|
+
RSpec.configure do |config|
|
50
|
+
config.after(:each) do
|
51
|
+
Delayed::Worker.reset
|
52
|
+
end
|
53
|
+
end
|
data/spec/test_backend_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Delayed::Backend::Test::Job do
|
4
4
|
it_should_behave_like 'a delayed_job backend'
|
5
|
-
|
5
|
+
|
6
6
|
describe "#reload" do
|
7
7
|
it 'should cause the payload object to be reloaded' do
|
8
8
|
job = "foo".delay.length
|
@@ -10,4 +10,4 @@ describe Delayed::Backend::Test::Job do
|
|
10
10
|
o.object_id.should_not == job.reload.payload_object.object_id
|
11
11
|
end
|
12
12
|
end
|
13
|
-
end
|
13
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delayed_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 3.0.
|
9
|
+
- 2
|
10
|
+
version: 3.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matt Griffin
|
@@ -20,7 +20,7 @@ autorequire:
|
|
20
20
|
bindir: bin
|
21
21
|
cert_chain: []
|
22
22
|
|
23
|
-
date: 2012-
|
23
|
+
date: 2012-04-03 00:00:00 Z
|
24
24
|
dependencies:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
@@ -56,46 +56,46 @@ dependencies:
|
|
56
56
|
version_requirements: &id003 !ruby/object:Gem::Requirement
|
57
57
|
none: false
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
hash:
|
61
|
+
hash: 7
|
62
62
|
segments:
|
63
|
+
- 3
|
63
64
|
- 0
|
64
|
-
version: "0"
|
65
|
+
version: "3.0"
|
65
66
|
requirement: *id003
|
66
67
|
type: :development
|
67
68
|
prerelease: false
|
68
|
-
name:
|
69
|
+
name: actionmailer
|
69
70
|
- !ruby/object:Gem::Dependency
|
70
71
|
version_requirements: &id004 !ruby/object:Gem::Requirement
|
71
72
|
none: false
|
72
73
|
requirements:
|
73
74
|
- - ~>
|
74
75
|
- !ruby/object:Gem::Version
|
75
|
-
hash:
|
76
|
+
hash: 3
|
76
77
|
segments:
|
77
|
-
-
|
78
|
+
- 2
|
78
79
|
- 0
|
79
|
-
version: "
|
80
|
+
version: "2.0"
|
80
81
|
requirement: *id004
|
81
82
|
type: :development
|
82
83
|
prerelease: false
|
83
|
-
name:
|
84
|
+
name: rspec
|
84
85
|
- !ruby/object:Gem::Dependency
|
85
86
|
version_requirements: &id005 !ruby/object:Gem::Requirement
|
86
87
|
none: false
|
87
88
|
requirements:
|
88
|
-
- -
|
89
|
+
- - ">="
|
89
90
|
- !ruby/object:Gem::Version
|
90
91
|
hash: 3
|
91
92
|
segments:
|
92
|
-
- 2
|
93
93
|
- 0
|
94
|
-
version: "
|
94
|
+
version: "0"
|
95
95
|
requirement: *id005
|
96
96
|
type: :development
|
97
97
|
prerelease: false
|
98
|
-
name:
|
98
|
+
name: rake
|
99
99
|
- !ruby/object:Gem::Dependency
|
100
100
|
version_requirements: &id006 !ruby/object:Gem::Requirement
|
101
101
|
none: false
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
requirement: *id006
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
name:
|
112
|
+
name: simplecov
|
113
113
|
description: |-
|
114
114
|
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.
|
115
115
|
|