delayed_job 2.1.0.pre → 2.1.0.pre2
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 +1 -16
- data/lib/delayed/backend/active_record.rb +12 -5
- data/lib/delayed/backend/base.rb +12 -3
- data/lib/delayed/backend/shared_spec.rb +472 -0
- data/lib/delayed/command.rb +4 -4
- data/lib/delayed/message_sending.rb +8 -6
- data/lib/delayed/performable_method.rb +9 -1
- data/lib/delayed/tasks.rb +2 -6
- data/lib/delayed/worker.rb +12 -12
- data/lib/delayed_job.rb +0 -4
- data/spec/{backend/active_record_job_spec.rb → active_record_job_spec.rb} +1 -11
- data/spec/message_sending_spec.rb +8 -1
- data/spec/performable_method_spec.rb +19 -1
- data/spec/sample_jobs.rb +36 -0
- data/spec/spec_helper.rb +35 -13
- data/spec/worker_spec.rb +14 -191
- data/spec/yaml_ext_spec.rb +16 -0
- metadata +24 -103
- data/.gitignore +0 -2
- data/Rakefile +0 -53
- data/VERSION +0 -1
- data/benchmarks.rb +0 -33
- data/delayed_job.gemspec +0 -125
- data/lib/delayed/backend/couch_rest.rb +0 -109
- data/lib/delayed/backend/data_mapper.rb +0 -121
- data/lib/delayed/backend/mongo_mapper.rb +0 -106
- data/spec/backend/couch_rest_job_spec.rb +0 -15
- data/spec/backend/data_mapper_job_spec.rb +0 -16
- data/spec/backend/mongo_mapper_job_spec.rb +0 -94
- data/spec/backend/shared_backend_spec.rb +0 -273
- data/spec/setup/active_record.rb +0 -33
- data/spec/setup/couch_rest.rb +0 -7
- data/spec/setup/data_mapper.rb +0 -8
- data/spec/setup/mongo_mapper.rb +0 -17
data/lib/delayed/command.rb
CHANGED
@@ -10,7 +10,7 @@ module Delayed
|
|
10
10
|
@files_to_reopen = []
|
11
11
|
@options = {
|
12
12
|
:quiet => true,
|
13
|
-
:pid_dir => "#{
|
13
|
+
:pid_dir => "#{Rails.root}/tmp/pids"
|
14
14
|
}
|
15
15
|
|
16
16
|
@worker_count = 1
|
@@ -80,18 +80,18 @@ module Delayed
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def run(worker_name = nil)
|
83
|
-
Dir.chdir(
|
83
|
+
Dir.chdir(Rails.root)
|
84
84
|
|
85
85
|
# Re-open file handles
|
86
86
|
@files_to_reopen.each do |file|
|
87
87
|
begin
|
88
|
-
file.reopen file.path
|
88
|
+
file.reopen file.path, "a+"
|
89
89
|
file.sync = true
|
90
90
|
rescue ::Exception
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
Delayed::Worker.logger = Logger.new(File.join(
|
94
|
+
Delayed::Worker.logger = Logger.new(File.join(Rails.root, 'log', 'delayed_job.log'))
|
95
95
|
Delayed::Worker.backend.after_fork
|
96
96
|
|
97
97
|
worker = Delayed::Worker.new(@options)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support/basic_object'
|
2
|
+
require 'active_support/core_ext/module/aliasing'
|
2
3
|
|
3
4
|
module Delayed
|
4
5
|
class DelayProxy < ActiveSupport::BasicObject
|
@@ -6,14 +7,15 @@ module Delayed
|
|
6
7
|
@target = target
|
7
8
|
@options = options
|
8
9
|
end
|
9
|
-
|
10
|
+
|
10
11
|
def method_missing(method, *args)
|
11
|
-
Job.create
|
12
|
-
:payload_object => PerformableMethod.new(@target, method.to_sym, args)
|
13
|
-
|
12
|
+
Job.create({
|
13
|
+
:payload_object => PerformableMethod.new(@target, method.to_sym, args),
|
14
|
+
:priority => ::Delayed::Worker.default_priority
|
15
|
+
}.merge(@options))
|
14
16
|
end
|
15
17
|
end
|
16
|
-
|
18
|
+
|
17
19
|
module MessageSending
|
18
20
|
def delay(options = {})
|
19
21
|
DelayProxy.new(self, options)
|
@@ -41,4 +43,4 @@ module Delayed
|
|
41
43
|
end
|
42
44
|
end
|
43
45
|
end
|
44
|
-
end
|
46
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Delayed
|
2
2
|
class PerformableMethod < Struct.new(:object, :method, :args)
|
3
3
|
def initialize(object, method, args)
|
4
|
-
raise NoMethodError, "undefined method `#{method}' for #{object.inspect}" unless object.respond_to?(method)
|
4
|
+
raise NoMethodError, "undefined method `#{method}' for #{object.inspect}" unless object.respond_to?(method, true)
|
5
5
|
|
6
6
|
self.object = object
|
7
7
|
self.args = args
|
@@ -15,5 +15,13 @@ module Delayed
|
|
15
15
|
def perform
|
16
16
|
object.send(method, *args) if object
|
17
17
|
end
|
18
|
+
|
19
|
+
def method_missing(symbol, *args)
|
20
|
+
object.respond_to?(symbol) ? object.send(symbol, *args) : super
|
21
|
+
end
|
22
|
+
|
23
|
+
def respond_to?(symbol, include_private=false)
|
24
|
+
object.respond_to?(symbol, include_private) || super
|
25
|
+
end
|
18
26
|
end
|
19
27
|
end
|
data/lib/delayed/tasks.rb
CHANGED
@@ -1,15 +1,11 @@
|
|
1
|
-
# Re-definitions are appended to existing tasks
|
2
|
-
task :environment
|
3
|
-
task :merb_env
|
4
|
-
|
5
1
|
namespace :jobs do
|
6
2
|
desc "Clear the delayed_job queue."
|
7
|
-
task :clear =>
|
3
|
+
task :clear => :environment do
|
8
4
|
Delayed::Job.delete_all
|
9
5
|
end
|
10
6
|
|
11
7
|
desc "Start a delayed_job worker."
|
12
|
-
task :work =>
|
8
|
+
task :work => :environment do
|
13
9
|
Delayed::Worker.new(:min_priority => ENV['MIN_PRIORITY'], :max_priority => ENV['MAX_PRIORITY']).start
|
14
10
|
end
|
15
11
|
end
|
data/lib/delayed/worker.rb
CHANGED
@@ -2,21 +2,23 @@ require 'timeout'
|
|
2
2
|
require 'active_support/core_ext/numeric/time'
|
3
3
|
require 'active_support/core_ext/class/attribute_accessors'
|
4
4
|
require 'active_support/core_ext/kernel'
|
5
|
+
require 'logger'
|
5
6
|
|
6
7
|
module Delayed
|
7
8
|
class Worker
|
8
|
-
cattr_accessor :min_priority, :max_priority, :max_attempts, :max_run_time, :sleep_delay, :logger
|
9
|
+
cattr_accessor :min_priority, :max_priority, :max_attempts, :max_run_time, :default_priority, :sleep_delay, :logger
|
9
10
|
self.sleep_delay = 5
|
10
11
|
self.max_attempts = 25
|
11
12
|
self.max_run_time = 4.hours
|
13
|
+
self.default_priority = 0
|
12
14
|
|
13
15
|
# By default failed jobs are destroyed after too many attempts. If you want to keep them around
|
14
16
|
# (perhaps to inspect the reason for the failure), set this to false.
|
15
17
|
cattr_accessor :destroy_failed_jobs
|
16
18
|
self.destroy_failed_jobs = true
|
17
19
|
|
18
|
-
self.logger = if defined?(
|
19
|
-
|
20
|
+
self.logger = if defined?(Rails)
|
21
|
+
Rails.logger
|
20
22
|
elsif defined?(RAILS_DEFAULT_LOGGER)
|
21
23
|
RAILS_DEFAULT_LOGGER
|
22
24
|
end
|
@@ -36,14 +38,7 @@ module Delayed
|
|
36
38
|
end
|
37
39
|
|
38
40
|
def self.guess_backend
|
39
|
-
self.backend ||= if defined?(ActiveRecord)
|
40
|
-
:active_record
|
41
|
-
elsif defined?(MongoMapper)
|
42
|
-
:mongo_mapper
|
43
|
-
else
|
44
|
-
logger.warn "Could not decide on a backend, defaulting to active_record"
|
45
|
-
:active_record
|
46
|
-
end
|
41
|
+
self.backend ||= :active_record if defined?(ActiveRecord)
|
47
42
|
end
|
48
43
|
|
49
44
|
def initialize(options={})
|
@@ -142,7 +137,12 @@ module Delayed
|
|
142
137
|
|
143
138
|
if job.payload_object.respond_to? :on_permanent_failure
|
144
139
|
say "Running on_permanent_failure hook"
|
145
|
-
job.payload_object.on_permanent_failure
|
140
|
+
failure_method = job.payload_object.method(:on_permanent_failure)
|
141
|
+
if failure_method.arity == 1
|
142
|
+
failure_method.call(job)
|
143
|
+
else
|
144
|
+
failure_method.call
|
145
|
+
end
|
146
146
|
end
|
147
147
|
|
148
148
|
self.class.destroy_failed_jobs ? job.destroy : job.update_attributes(:failed_at => Delayed::Job.db_time_now)
|
data/lib/delayed_job.rb
CHANGED
@@ -9,7 +9,3 @@ require File.dirname(__FILE__) + '/delayed/railtie' if defined?(::Rails::Railtie
|
|
9
9
|
|
10
10
|
Object.send(:include, Delayed::MessageSending)
|
11
11
|
Module.send(:include, Delayed::MessageSending::ClassMethods)
|
12
|
-
|
13
|
-
if defined?(Merb::Plugins)
|
14
|
-
Merb::Plugins.add_rakefiles File.dirname(__FILE__) / 'delayed' / 'tasks'
|
15
|
-
end
|
@@ -1,22 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'backend/shared_backend_spec'
|
3
2
|
require 'delayed/backend/active_record'
|
4
3
|
|
5
4
|
describe Delayed::Backend::ActiveRecord::Job do
|
6
|
-
before(:all) do
|
7
|
-
@backend = Delayed::Backend::ActiveRecord::Job
|
8
|
-
end
|
9
|
-
|
10
|
-
before(:each) do
|
11
|
-
Delayed::Backend::ActiveRecord::Job.delete_all
|
12
|
-
SimpleJob.runs = 0
|
13
|
-
end
|
14
|
-
|
15
5
|
after do
|
16
6
|
Time.zone = nil
|
17
7
|
end
|
18
8
|
|
19
|
-
it_should_behave_like 'a backend'
|
9
|
+
it_should_behave_like 'a delayed_job backend'
|
20
10
|
|
21
11
|
context "db_time_now" do
|
22
12
|
it "should return time in current time zone if set" do
|
@@ -33,7 +33,14 @@ describe Delayed::MessageSending do
|
|
33
33
|
job.payload_object.args.should == ['l']
|
34
34
|
}.should change { Delayed::Job.count }.by(1)
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
|
+
it "should set default priority" do
|
38
|
+
Delayed::Worker.default_priority = 99
|
39
|
+
job = Object.delay.to_s
|
40
|
+
job.priority.should == 99
|
41
|
+
Delayed::Worker.default_priority = 0
|
42
|
+
end
|
43
|
+
|
37
44
|
it "should set job options" do
|
38
45
|
run_at = Time.parse('2010-05-03 12:55 AM')
|
39
46
|
job = Object.delay(:priority => 20, :run_at => run_at).to_s
|
@@ -20,11 +20,29 @@ describe Delayed::PerformableMethod 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
|
23
30
|
end
|
24
31
|
|
25
|
-
it "should raise a
|
32
|
+
it "should raise a NoMethodError if target method doesn't exist" do
|
26
33
|
lambda {
|
27
34
|
Delayed::PerformableMethod.new(Object, :method_that_does_not_exist, [])
|
28
35
|
}.should raise_error(NoMethodError)
|
29
36
|
end
|
37
|
+
|
38
|
+
it "should not raise NoMethodError if target method is private" do
|
39
|
+
clazz = Class.new do
|
40
|
+
def private_method
|
41
|
+
end
|
42
|
+
private :private_method
|
43
|
+
end
|
44
|
+
lambda {
|
45
|
+
Delayed::PerformableMethod.new(clazz.new, :private_method, [])
|
46
|
+
}.should_not raise_error(NoMethodError)
|
47
|
+
end
|
30
48
|
end
|
data/spec/sample_jobs.rb
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
class NamedJob < Struct.new(:perform)
|
2
|
+
def display_name
|
3
|
+
'named_job'
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
1
7
|
class SimpleJob
|
2
8
|
cattr_accessor :runs; self.runs = 0
|
3
9
|
def perform; @@runs += 1; end
|
@@ -23,3 +29,33 @@ module M
|
|
23
29
|
def perform; @@runs += 1; end
|
24
30
|
end
|
25
31
|
end
|
32
|
+
|
33
|
+
class SuccessfulCallbackJob
|
34
|
+
cattr_accessor :messages
|
35
|
+
|
36
|
+
def before(job)
|
37
|
+
SuccessfulCallbackJob.messages << 'before perform'
|
38
|
+
end
|
39
|
+
|
40
|
+
def perform
|
41
|
+
SuccessfulCallbackJob.messages << 'perform'
|
42
|
+
end
|
43
|
+
|
44
|
+
def after(job, error = nil)
|
45
|
+
SuccessfulCallbackJob.messages << 'after perform'
|
46
|
+
end
|
47
|
+
|
48
|
+
def success(job)
|
49
|
+
SuccessfulCallbackJob.messages << 'success!'
|
50
|
+
end
|
51
|
+
|
52
|
+
def failure(job, error)
|
53
|
+
SuccessfulCallbackJob.messages << "error: #{error.class}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class FailureCallbackJob < SuccessfulCallbackJob
|
58
|
+
def perform
|
59
|
+
raise "failure job"
|
60
|
+
end
|
61
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,31 +1,53 @@
|
|
1
1
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
+
require 'bundler/setup'
|
4
5
|
require 'spec'
|
5
6
|
require 'logger'
|
6
7
|
|
7
8
|
gem 'activerecord', ENV['RAILS_VERSION'] if ENV['RAILS_VERSION']
|
8
9
|
|
9
10
|
require 'delayed_job'
|
10
|
-
require '
|
11
|
+
require 'delayed/backend/shared_spec'
|
11
12
|
|
12
13
|
Delayed::Worker.logger = Logger.new('/tmp/dj.log')
|
13
14
|
RAILS_ENV = 'test'
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
16
|
+
require 'active_record'
|
17
|
+
|
18
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
19
|
+
ActiveRecord::Base.logger = Delayed::Worker.logger
|
20
|
+
ActiveRecord::Migration.verbose = false
|
21
|
+
|
22
|
+
ActiveRecord::Schema.define do
|
23
|
+
create_table :delayed_jobs, :force => true do |table|
|
24
|
+
table.integer :priority, :default => 0
|
25
|
+
table.integer :attempts, :default => 0
|
26
|
+
table.text :handler
|
27
|
+
table.text :last_error
|
28
|
+
table.datetime :run_at
|
29
|
+
table.datetime :locked_at
|
30
|
+
table.datetime :failed_at
|
31
|
+
table.string :locked_by
|
32
|
+
table.timestamps
|
25
33
|
end
|
34
|
+
|
35
|
+
add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
|
36
|
+
|
37
|
+
create_table :stories, :force => true do |table|
|
38
|
+
table.string :text
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Purely useful for test cases...
|
43
|
+
class Story < ActiveRecord::Base
|
44
|
+
def tell; text; end
|
45
|
+
def whatever(n, _); tell*n; end
|
46
|
+
|
47
|
+
handle_asynchronously :whatever
|
26
48
|
end
|
27
49
|
|
28
|
-
Delayed::Worker.backend =
|
50
|
+
Delayed::Worker.backend = :active_record
|
29
51
|
|
30
52
|
# Add this directory so the ActiveSupport autoloading works
|
31
|
-
ActiveSupport::Dependencies.
|
53
|
+
ActiveSupport::Dependencies.autoload_paths << File.dirname(__FILE__)
|
data/spec/worker_spec.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Delayed::Worker do
|
4
|
-
def job_create(opts = {})
|
5
|
-
Delayed::Job.create(opts.merge(:payload_object => SimpleJob.new))
|
6
|
-
end
|
7
|
-
|
8
4
|
describe "backend=" do
|
9
5
|
before do
|
10
6
|
@clazz = Class.new
|
@@ -14,201 +10,28 @@ describe Delayed::Worker do
|
|
14
10
|
it "should set the Delayed::Job constant to the backend" do
|
15
11
|
Delayed::Job.should == @clazz
|
16
12
|
end
|
17
|
-
|
13
|
+
|
18
14
|
it "should set backend with a symbol" do
|
19
15
|
Delayed::Worker.backend = :active_record
|
20
16
|
Delayed::Worker.backend.should == Delayed::Backend::ActiveRecord::Job
|
21
17
|
end
|
22
18
|
end
|
23
|
-
|
24
|
-
BACKENDS.each do |backend|
|
25
|
-
describe "with the #{backend} backend" do
|
26
|
-
before do
|
27
|
-
Delayed::Worker.backend = backend
|
28
|
-
Delayed::Job.delete_all
|
29
|
-
|
30
|
-
@worker = Delayed::Worker.new(:max_priority => nil, :min_priority => nil, :quiet => true)
|
31
|
-
|
32
|
-
SimpleJob.runs = 0
|
33
|
-
end
|
34
|
-
|
35
|
-
describe "running a job" do
|
36
|
-
it "should fail after Worker.max_run_time" do
|
37
|
-
begin
|
38
|
-
old_max_run_time = Delayed::Worker.max_run_time
|
39
|
-
Delayed::Worker.max_run_time = 1.second
|
40
|
-
@job = Delayed::Job.create :payload_object => LongRunningJob.new
|
41
|
-
@worker.run(@job)
|
42
|
-
@job.reload.last_error.should =~ /expired/
|
43
|
-
@job.attempts.should == 1
|
44
|
-
ensure
|
45
|
-
Delayed::Worker.max_run_time = old_max_run_time
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
context "worker prioritization" do
|
51
|
-
before(:each) do
|
52
|
-
@worker = Delayed::Worker.new(:max_priority => 5, :min_priority => -5, :quiet => true)
|
53
|
-
end
|
54
|
-
|
55
|
-
it "should only work_off jobs that are >= min_priority" do
|
56
|
-
job_create(:priority => -10)
|
57
|
-
job_create(:priority => 0)
|
58
|
-
@worker.work_off
|
59
|
-
|
60
|
-
SimpleJob.runs.should == 1
|
61
|
-
end
|
62
|
-
|
63
|
-
it "should only work_off jobs that are <= max_priority" do
|
64
|
-
job_create(:priority => 10)
|
65
|
-
job_create(:priority => 0)
|
66
|
-
|
67
|
-
@worker.work_off
|
68
|
-
|
69
|
-
SimpleJob.runs.should == 1
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
context "while running with locked and expired jobs" do
|
74
|
-
before(:each) do
|
75
|
-
@worker.name = 'worker1'
|
76
|
-
end
|
77
|
-
|
78
|
-
it "should not run jobs locked by another worker" do
|
79
|
-
job_create(:locked_by => 'other_worker', :locked_at => (Delayed::Job.db_time_now - 1.minutes))
|
80
|
-
lambda { @worker.work_off }.should_not change { SimpleJob.runs }
|
81
|
-
end
|
82
|
-
|
83
|
-
it "should run open jobs" do
|
84
|
-
job_create
|
85
|
-
lambda { @worker.work_off }.should change { SimpleJob.runs }.from(0).to(1)
|
86
|
-
end
|
87
|
-
|
88
|
-
it "should run expired jobs" do
|
89
|
-
expired_time = Delayed::Job.db_time_now - (1.minutes + Delayed::Worker.max_run_time)
|
90
|
-
job_create(:locked_by => 'other_worker', :locked_at => expired_time)
|
91
|
-
lambda { @worker.work_off }.should change { SimpleJob.runs }.from(0).to(1)
|
92
|
-
end
|
93
|
-
|
94
|
-
it "should run own jobs" do
|
95
|
-
job_create(:locked_by => @worker.name, :locked_at => (Delayed::Job.db_time_now - 1.minutes))
|
96
|
-
lambda { @worker.work_off }.should change { SimpleJob.runs }.from(0).to(1)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
describe "failed jobs" do
|
101
|
-
before do
|
102
|
-
# reset defaults
|
103
|
-
Delayed::Worker.destroy_failed_jobs = true
|
104
|
-
Delayed::Worker.max_attempts = 25
|
105
19
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
Delayed::Worker.destroy_failed_jobs = false
|
111
|
-
Delayed::Worker.max_attempts = 1
|
112
|
-
@worker.run(@job)
|
113
|
-
@job.reload
|
114
|
-
@job.last_error.should =~ /did not work/
|
115
|
-
@job.last_error.should =~ /worker_spec.rb/
|
116
|
-
@job.attempts.should == 1
|
117
|
-
@job.failed_at.should_not be_nil
|
118
|
-
end
|
119
|
-
|
120
|
-
it "should re-schedule jobs after failing" do
|
121
|
-
@worker.run(@job)
|
122
|
-
@job.reload
|
123
|
-
@job.last_error.should =~ /did not work/
|
124
|
-
@job.last_error.should =~ /sample_jobs.rb:8:in `perform'/
|
125
|
-
@job.attempts.should == 1
|
126
|
-
@job.run_at.should > Delayed::Job.db_time_now - 10.minutes
|
127
|
-
@job.run_at.should < Delayed::Job.db_time_now + 10.minutes
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
context "reschedule" do
|
132
|
-
before do
|
133
|
-
@job = Delayed::Job.create :payload_object => SimpleJob.new
|
134
|
-
end
|
135
|
-
|
136
|
-
share_examples_for "any failure more than Worker.max_attempts times" do
|
137
|
-
context "when the job's payload has an #on_permanent_failure hook" do
|
138
|
-
before do
|
139
|
-
@job = Delayed::Job.create :payload_object => OnPermanentFailureJob.new
|
140
|
-
@job.payload_object.should respond_to :on_permanent_failure
|
141
|
-
end
|
142
|
-
|
143
|
-
it "should run that hook" do
|
144
|
-
@job.payload_object.should_receive :on_permanent_failure
|
145
|
-
Delayed::Worker.max_attempts.times { @worker.reschedule(@job) }
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
context "when the job's payload has no #on_permanent_failure hook" do
|
150
|
-
# It's a little tricky to test this in a straightforward way,
|
151
|
-
# because putting a should_not_receive expectation on
|
152
|
-
# @job.payload_object.on_permanent_failure makes that object
|
153
|
-
# incorrectly return true to
|
154
|
-
# payload_object.respond_to? :on_permanent_failure, which is what
|
155
|
-
# reschedule uses to decide whether to call on_permanent_failure.
|
156
|
-
# So instead, we just make sure that the payload_object as it
|
157
|
-
# already stands doesn't respond_to? on_permanent_failure, then
|
158
|
-
# shove it through the iterated reschedule loop and make sure we
|
159
|
-
# don't get a NoMethodError (caused by calling that nonexistent
|
160
|
-
# on_permanent_failure method).
|
161
|
-
|
162
|
-
before do
|
163
|
-
@job.payload_object.should_not respond_to(:on_permanent_failure)
|
164
|
-
end
|
165
|
-
|
166
|
-
it "should not try to run that hook" do
|
167
|
-
lambda do
|
168
|
-
Delayed::Worker.max_attempts.times { @worker.reschedule(@job) }
|
169
|
-
end.should_not raise_exception(NoMethodError)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
context "and we want to destroy jobs" do
|
175
|
-
before do
|
176
|
-
Delayed::Worker.destroy_failed_jobs = true
|
177
|
-
end
|
178
|
-
|
179
|
-
it_should_behave_like "any failure more than Worker.max_attempts times"
|
180
|
-
|
181
|
-
it "should be destroyed if it failed more than Worker.max_attempts times" do
|
182
|
-
@job.should_receive(:destroy)
|
183
|
-
Delayed::Worker.max_attempts.times { @worker.reschedule(@job) }
|
184
|
-
end
|
185
|
-
|
186
|
-
it "should not be destroyed if failed fewer than Worker.max_attempts times" do
|
187
|
-
@job.should_not_receive(:destroy)
|
188
|
-
(Delayed::Worker.max_attempts - 1).times { @worker.reschedule(@job) }
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
context "and we don't want to destroy jobs" do
|
193
|
-
before do
|
194
|
-
Delayed::Worker.destroy_failed_jobs = false
|
195
|
-
end
|
196
|
-
|
197
|
-
it_should_behave_like "any failure more than Worker.max_attempts times"
|
20
|
+
describe "guess_backend" do
|
21
|
+
after do
|
22
|
+
Delayed::Worker.backend = :active_record
|
23
|
+
end
|
198
24
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
25
|
+
it "should set to active_record if nil" do
|
26
|
+
Delayed::Worker.backend = nil
|
27
|
+
lambda {
|
28
|
+
Delayed::Worker.guess_backend
|
29
|
+
}.should change { Delayed::Worker.backend }.to(Delayed::Backend::ActiveRecord::Job)
|
30
|
+
end
|
204
31
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
32
|
+
it "should not override the existing backend" do
|
33
|
+
Delayed::Worker.backend = Class.new
|
34
|
+
lambda { Delayed::Worker.guess_backend }.should_not change { Delayed::Worker.backend }
|
211
35
|
end
|
212
36
|
end
|
213
|
-
|
214
37
|
end
|