delayed_job 4.0.2 → 4.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YjQ5ZWQ1YmMzNWIxNTVhYzllZTdhNWI0ZWI4MzAwMzA3YjdjN2IyYg==
5
- data.tar.gz: !binary |-
6
- MDJmZDk3ZjJjYmNkZWFiMmIzNTU5MGQzMmNiOWM4Mzk2ODE0ODkzZg==
2
+ SHA1:
3
+ metadata.gz: f8464e2a78c559301360d0c083d940e73f314406
4
+ data.tar.gz: 819bd2dc775364ed9e6311be0a82fb3bdc20d6a6
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZGVkODJjNTNkYTc5YmJkYWIxN2NiZjVkZTA4M2ExYzg5ZjU5NjRkNDBmMjAz
10
- ZWVkNjcxMWRlZmZmOTU4OGNiMTU0N2E2N2QwODczYmQyNjI5YmM3MDc3ZTNm
11
- YTI2Njk1NzBjZDFmYTkxZmE1YmVkYzJkOWI3NDZiODc2NDc1NjM=
12
- data.tar.gz: !binary |-
13
- OTBkOGMwYjNiZGIxNWMxODk3ZjI1OWFlZTU5NDlmNTZiZTBhNGQ0ZTY1ZjRm
14
- ZWYwYzFkZjgxMTE5OWJhMzg3NWU0YzU3MWNhMGJmMjg0N2Y4NDk5MjY5ZDE3
15
- NDMxYWFmOTU0M2FhZWJmMzIyYmNlMDZiYjJjODg0NjM0NWVkODQ=
6
+ metadata.gz: c7d9b76c5f6244b37e79f2df7f5d5d270bd0769366ab0d93967ca02bd9ff434b98801ed92032815d0e0dd1abba5f9617881dd64aeabf09ed0700066f59985a3f
7
+ data.tar.gz: 3f99c1bcddf3c835a4eea9cd200b559d1d284d169633016e79b0303549583be78cdfd888671139fe83ecec669b140171bb255d3f4bf03eaa9a4a45ed2c2bc7e2
@@ -1,3 +1,10 @@
1
+ 4.0.3 - 2014-09-04
2
+ ==================
3
+ * Added --pools option to delayed_job command
4
+ * Removed a bunch of the Psych hacks
5
+ * Improved deserialization error reporting
6
+ * Misc bug fixes
7
+
1
8
  4.0.2 - 2014-06-24
2
9
  ==================
3
10
  * Add support for RSpec 3
data/README.md CHANGED
@@ -190,6 +190,11 @@ You can then do the following:
190
190
  RAILS_ENV=production script/delayed_job --queue=tracking start
191
191
  RAILS_ENV=production script/delayed_job --queues=mailers,tasks start
192
192
 
193
+ # Use the --pool option to specify a worker pool. You can use this option multiple times to start different numbers of workers for different queues.
194
+ # The following command will start 1 worker for the tracking queue,
195
+ # 2 workers for the mailers and tasks queues, and 2 workers for any jobs:
196
+ RAILS_ENV=production script/delayed_job --pool=tracking --pool=mailers,tasks:2 --pool=*:2 start
197
+
193
198
  # Runs all available jobs and then exits
194
199
  RAILS_ENV=production script/delayed_job start --exit-on-complete
195
200
  # or to run in the foreground
@@ -310,22 +315,22 @@ end
310
315
 
311
316
  On failure, the job is scheduled again in 5 seconds + N ** 4, where N is the number of retries.
312
317
 
313
- The default Worker.max_attempts is 25. After this, the job either deleted (default), or left in the database with "failed_at" set.
318
+ The default `Worker.max_attempts` is 25. After this, the job either deleted (default), or left in the database with "failed_at" set.
314
319
  With the default of 25 attempts, the last retry will be 20 days later, with the last interval being almost 100 hours.
315
320
 
316
- The default Worker.max_run_time is 4.hours. If your job takes longer than that, another computer could pick it up. It's up to you to
321
+ The default `Worker.max_run_time` is 4.hours. If your job takes longer than that, another computer could pick it up. It's up to you to
317
322
  make sure your job doesn't exceed this time. You should set this to the longest time you think the job could take.
318
323
 
319
324
  By default, it will delete failed jobs (and it always deletes successful jobs). If you want to keep failed jobs, set
320
- Delayed::Worker.destroy_failed_jobs = false. The failed jobs will be marked with non-null failed_at.
325
+ `Delayed::Worker.destroy_failed_jobs = false`. The failed jobs will be marked with non-null failed_at.
321
326
 
322
- 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.
327
+ 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.
323
328
 
324
- 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.
329
+ 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`.
325
330
 
326
- 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.
331
+ 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`.
327
332
 
328
- It is possible to disable delayed jobs for testing purposes. Set Delayed::Worker.delay_jobs = false to execute all jobs realtime.
333
+ It is possible to disable delayed jobs for testing purposes. Set `Delayed::Worker.delay_jobs = false` to execute all jobs realtime.
329
334
 
330
335
  Here is an example of changing job parameters in Rails:
331
336
 
data/Rakefile CHANGED
@@ -7,4 +7,9 @@ RSpec::Core::RakeTask.new do |r|
7
7
  r.verbose = false
8
8
  end
9
9
 
10
- task :default => :spec
10
+ task :test => :spec
11
+
12
+ require 'rubocop/rake_task'
13
+ RuboCop::RakeTask.new
14
+
15
+ task :default => [:spec, :rubocop]
@@ -1,9 +1,9 @@
1
1
  Gem::Specification.new do |spec|
2
- spec.add_dependency 'activesupport', ['>= 3.0', '< 4.2']
3
- spec.authors = ["Brandon Keepers", "Brian Ryckbost", "Chris Gaffney", "David Genord II", "Erik Michaels-Ober", "Matt Griffin", "Steve Richert", "Tobias Lütke"]
4
- spec.description = "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."
2
+ spec.add_dependency 'activesupport', ['>= 3.0', '< 4.2']
3
+ spec.authors = ['Brandon Keepers', 'Brian Ryckbost', 'Chris Gaffney', 'David Genord II', 'Erik Michaels-Ober', 'Matt Griffin', 'Steve Richert', 'Tobias Lütke']
4
+ spec.description = '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.'
5
5
  spec.email = ['brian@collectiveidea.com']
6
- spec.files = %w(CHANGELOG.md CONTRIBUTING.md LICENSE.md README.md Rakefile delayed_job.gemspec)
6
+ spec.files = %w[CHANGELOG.md CONTRIBUTING.md LICENSE.md README.md Rakefile delayed_job.gemspec]
7
7
  spec.files += Dir.glob('{contrib,lib,recipes,spec}/**/*')
8
8
  spec.homepage = 'http://github.com/collectiveidea/delayed_job'
9
9
  spec.licenses = ['MIT']
@@ -11,5 +11,5 @@ Gem::Specification.new do |spec|
11
11
  spec.require_paths = ['lib']
12
12
  spec.summary = 'Database-backed asynchronous priority queue system -- Extracted from Shopify'
13
13
  spec.test_files = Dir.glob('spec/**/*')
14
- spec.version = '4.0.2'
14
+ spec.version = '4.0.3'
15
15
  end
@@ -16,7 +16,7 @@ module Delayed
16
16
  options[:payload_object] ||= args.shift
17
17
 
18
18
  if args.size > 0
19
- warn "[DEPRECATION] Passing multiple arguments to `#enqueue` is deprecated. Pass a hash with :priority and :run_at."
19
+ warn '[DEPRECATION] Passing multiple arguments to `#enqueue` is deprecated. Pass a hash with :priority and :run_at.'
20
20
  options[:priority] = args.first || options[:priority]
21
21
  options[:run_at] = args[1]
22
22
  end
@@ -26,7 +26,7 @@ module Delayed
26
26
  end
27
27
 
28
28
  if Delayed::Worker.delay_jobs
29
- self.new(options).tap do |job|
29
+ new(options).tap do |job|
30
30
  Delayed::Worker.lifecycle.run_callbacks(:enqueue, job) do
31
31
  job.hook(:enqueue)
32
32
  job.save
@@ -48,7 +48,7 @@ module Delayed
48
48
  end
49
49
 
50
50
  # Allow the backend to attempt recovery from reserve errors
51
- def recover_from(error)
51
+ def recover_from(_error)
52
52
  end
53
53
 
54
54
  # Hook method that is called before a new worker is forked
@@ -60,7 +60,7 @@ module Delayed
60
60
  end
61
61
 
62
62
  def work_off(num = 100)
63
- warn "[DEPRECATION] `Delayed::Job.work_off` is deprecated. Use `Delayed::Worker.new.work_off instead."
63
+ warn '[DEPRECATION] `Delayed::Job.work_off` is deprecated. Use `Delayed::Worker.new.work_off instead.'
64
64
  Delayed::Worker.new.work_off(num)
65
65
  end
66
66
  end
@@ -70,12 +70,10 @@ module Delayed
70
70
  end
71
71
  alias_method :failed, :failed?
72
72
 
73
- ParseObjectFromYaml = /\!ruby\/\w+\:([^\s]+)/
73
+ ParseObjectFromYaml = /\!ruby\/\w+\:([^\s]+)/ # rubocop:disable ConstantName
74
74
 
75
75
  def name
76
- @name ||= payload_object.respond_to?(:display_name) ?
77
- payload_object.display_name :
78
- payload_object.class.name
76
+ @name ||= payload_object.respond_to?(:display_name) ? payload_object.display_name : payload_object.class.name
79
77
  rescue DeserializationError
80
78
  ParseObjectFromYaml.match(handler)[1]
81
79
  end
@@ -87,15 +85,14 @@ module Delayed
87
85
 
88
86
  def payload_object
89
87
  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)
88
+ # See https://github.com/dtao/safe_yaml
89
+ # When the method is there, we need to load our YAML like this...
90
+ @payload_object ||= YAML.load(handler, :safe => false)
93
91
  else
94
- @payload_object ||= YAML.load(self.handler)
92
+ @payload_object ||= YAML.load(handler)
95
93
  end
96
94
  rescue TypeError, LoadError, NameError, ArgumentError => e
97
- raise DeserializationError,
98
- "Job failed to load: #{e.message}. Handler: #{handler.inspect}"
95
+ raise DeserializationError, "Job failed to load: #{e.message}. Handler: #{handler.inspect}"
99
96
  end
100
97
 
101
98
  def invoke_job
@@ -104,7 +101,7 @@ module Delayed
104
101
  hook :before
105
102
  payload_object.perform
106
103
  hook :success
107
- rescue Exception => e
104
+ rescue => e
108
105
  hook :error, e
109
106
  raise e
110
107
  ensure
@@ -124,14 +121,15 @@ module Delayed
124
121
  method = payload_object.method(name)
125
122
  method.arity == 0 ? method.call : method.call(self, *args)
126
123
  end
127
- rescue DeserializationError
128
- # do nothing
124
+ rescue DeserializationError # rubocop:disable HandleExceptions
129
125
  end
130
126
 
131
127
  def reschedule_at
132
- payload_object.respond_to?(:reschedule_at) ?
133
- payload_object.reschedule_at(self.class.db_time_now, attempts) :
134
- self.class.db_time_now + (attempts ** 4) + 5
128
+ if payload_object.respond_to?(:reschedule_at)
129
+ payload_object.reschedule_at(self.class.db_time_now, attempts)
130
+ else
131
+ self.class.db_time_now + (attempts**4) + 5
132
+ end
135
133
  end
136
134
 
137
135
  def max_attempts
@@ -2,7 +2,7 @@ require File.expand_path('../../../../spec/sample_jobs', __FILE__)
2
2
 
3
3
  require 'active_support/core_ext'
4
4
 
5
- shared_examples_for "a delayed_job backend" do
5
+ shared_examples_for 'a delayed_job backend' do
6
6
  let(:worker) { Delayed::Worker.new }
7
7
 
8
8
  def create_job(opts = {})
@@ -22,74 +22,74 @@ shared_examples_for "a delayed_job backend" do
22
22
  Delayed::Worker.reset
23
23
  end
24
24
 
25
- it "sets run_at automatically if not set" do
26
- expect(described_class.create(:payload_object => ErrorJob.new ).run_at).not_to be_nil
25
+ it 'sets run_at automatically if not set' do
26
+ expect(described_class.create(:payload_object => ErrorJob.new).run_at).not_to be_nil
27
27
  end
28
28
 
29
- it "does not set run_at automatically if already set" do
29
+ it 'does not set run_at automatically if already set' do
30
30
  later = described_class.db_time_now + 5.minutes
31
31
  job = described_class.create(:payload_object => ErrorJob.new, :run_at => later)
32
32
  expect(job.run_at).to be_within(1).of(later)
33
33
  end
34
34
 
35
- describe "#reload" do
36
- it "reloads the payload" do
35
+ describe '#reload' do
36
+ it 'reloads the payload' do
37
37
  job = described_class.enqueue :payload_object => SimpleJob.new
38
38
  expect(job.payload_object.object_id).not_to eq(job.reload.payload_object.object_id)
39
39
  end
40
40
  end
41
41
 
42
- describe "enqueue" do
43
- context "with a hash" do
42
+ describe 'enqueue' do
43
+ context 'with a hash' do
44
44
  it "raises ArgumentError when handler doesn't respond_to :perform" do
45
- expect{described_class.enqueue(:payload_object => Object.new)}.to raise_error(ArgumentError)
45
+ expect { described_class.enqueue(:payload_object => Object.new) }.to raise_error(ArgumentError)
46
46
  end
47
47
 
48
- it "is able to set priority" do
48
+ it 'is able to set priority' do
49
49
  job = described_class.enqueue :payload_object => SimpleJob.new, :priority => 5
50
50
  expect(job.priority).to eq(5)
51
51
  end
52
52
 
53
- it "uses default priority" do
53
+ it 'uses default priority' do
54
54
  job = described_class.enqueue :payload_object => SimpleJob.new
55
55
  expect(job.priority).to eq(99)
56
56
  end
57
57
 
58
- it "is able to set run_at" do
58
+ it 'is able to set run_at' do
59
59
  later = described_class.db_time_now + 5.minutes
60
60
  job = described_class.enqueue :payload_object => SimpleJob.new, :run_at => later
61
61
  expect(job.run_at).to be_within(1).of(later)
62
62
  end
63
63
 
64
- it "is able to set queue" do
64
+ it 'is able to set queue' do
65
65
  job = described_class.enqueue :payload_object => SimpleJob.new, :queue => 'tracking'
66
66
  expect(job.queue).to eq('tracking')
67
67
  end
68
68
  end
69
69
 
70
- context "with multiple arguments" do
70
+ context 'with multiple arguments' do
71
71
  it "raises ArgumentError when handler doesn't respond_to :perform" do
72
- expect{described_class.enqueue(Object.new)}.to raise_error(ArgumentError)
72
+ expect { described_class.enqueue(Object.new) }.to raise_error(ArgumentError)
73
73
  end
74
74
 
75
- it "increases count after enqueuing items" do
75
+ it 'increases count after enqueuing items' do
76
76
  described_class.enqueue SimpleJob.new
77
77
  expect(described_class.count).to eq(1)
78
78
  end
79
79
 
80
- it "is able to set priority [DEPRECATED]" do
80
+ it 'is able to set priority [DEPRECATED]' do
81
81
  silence_warnings do
82
82
  job = described_class.enqueue SimpleJob.new, 5
83
83
  expect(job.priority).to eq(5)
84
84
  end
85
85
  end
86
86
 
87
- it "uses default priority when it is not set" do
87
+ it 'uses default priority when it is not set' do
88
88
  @job = described_class.enqueue SimpleJob.new
89
89
  expect(@job.priority).to eq(99)
90
90
  end
91
91
 
92
- it "is able to set run_at [DEPRECATED]" do
92
+ it 'is able to set run_at [DEPRECATED]' do
93
93
  silence_warnings do
94
94
  later = described_class.db_time_now + 5.minutes
95
95
  @job = described_class.enqueue SimpleJob.new, 5, later
@@ -97,41 +97,41 @@ shared_examples_for "a delayed_job backend" do
97
97
  end
98
98
  end
99
99
 
100
- it "works with jobs in modules" do
100
+ it 'works with jobs in modules' do
101
101
  M::ModuleJob.runs = 0
102
102
  job = described_class.enqueue M::ModuleJob.new
103
- expect{job.invoke_job}.to change { M::ModuleJob.runs }.from(0).to(1)
103
+ expect { job.invoke_job }.to change { M::ModuleJob.runs }.from(0).to(1)
104
104
  end
105
105
  end
106
106
 
107
- context "with delay_jobs = false" do
107
+ context 'with delay_jobs = false' do
108
108
  before(:each) do
109
109
  Delayed::Worker.delay_jobs = false
110
110
  end
111
111
 
112
- it "does not increase count after enqueuing items" do
112
+ it 'does not increase count after enqueuing items' do
113
113
  described_class.enqueue SimpleJob.new
114
114
  expect(described_class.count).to eq(0)
115
115
  end
116
116
 
117
- it "invokes the enqueued job" do
117
+ it 'invokes the enqueued job' do
118
118
  job = SimpleJob.new
119
119
  expect(job).to receive(:perform)
120
120
  described_class.enqueue job
121
121
  end
122
122
 
123
- it "returns a job, not the result of invocation" do
123
+ it 'returns a job, not the result of invocation' do
124
124
  expect(described_class.enqueue(SimpleJob.new)).to be_instance_of(described_class)
125
125
  end
126
126
  end
127
127
  end
128
128
 
129
- describe "callbacks" do
129
+ describe 'callbacks' do
130
130
  before(:each) do
131
131
  CallbackJob.messages = []
132
132
  end
133
133
 
134
- %w(before success after).each do |callback|
134
+ %w[before success after].each do |callback|
135
135
  it "calls #{callback} with job" do
136
136
  job = described_class.enqueue(CallbackJob.new)
137
137
  expect(job.payload_object).to receive(callback).with(job)
@@ -139,48 +139,48 @@ shared_examples_for "a delayed_job backend" do
139
139
  end
140
140
  end
141
141
 
142
- it "calls before and after callbacks" do
142
+ it 'calls before and after callbacks' do
143
143
  job = described_class.enqueue(CallbackJob.new)
144
- expect(CallbackJob.messages).to eq(["enqueue"])
144
+ expect(CallbackJob.messages).to eq(['enqueue'])
145
145
  job.invoke_job
146
- expect(CallbackJob.messages).to eq(["enqueue", "before", "perform", "success", "after"])
146
+ expect(CallbackJob.messages).to eq(%w[enqueue before perform success after])
147
147
  end
148
148
 
149
- it "calls the after callback with an error" do
149
+ it 'calls the after callback with an error' do
150
150
  job = described_class.enqueue(CallbackJob.new)
151
- expect(job.payload_object).to receive(:perform).and_raise(RuntimeError.new("fail"))
151
+ expect(job.payload_object).to receive(:perform).and_raise(RuntimeError.new('fail'))
152
152
 
153
- expect{job.invoke_job}.to raise_error
154
- expect(CallbackJob.messages).to eq(["enqueue", "before", "error: RuntimeError", "after"])
153
+ expect { job.invoke_job }.to raise_error
154
+ expect(CallbackJob.messages).to eq(['enqueue', 'before', 'error: RuntimeError', 'after'])
155
155
  end
156
156
 
157
- it "calls error when before raises an error" do
157
+ it 'calls error when before raises an error' do
158
158
  job = described_class.enqueue(CallbackJob.new)
159
- expect(job.payload_object).to receive(:before).and_raise(RuntimeError.new("fail"))
160
- expect{job.invoke_job}.to raise_error(RuntimeError)
161
- expect(CallbackJob.messages).to eq(["enqueue", "error: RuntimeError", "after"])
159
+ expect(job.payload_object).to receive(:before).and_raise(RuntimeError.new('fail'))
160
+ expect { job.invoke_job }.to raise_error(RuntimeError)
161
+ expect(CallbackJob.messages).to eq(['enqueue', 'error: RuntimeError', 'after'])
162
162
  end
163
163
  end
164
164
 
165
- describe "payload_object" do
166
- it "raises a DeserializationError when the job class is totally unknown" do
167
- job = described_class.new :handler => "--- !ruby/object:JobThatDoesNotExist {}"
168
- expect{job.payload_object}.to raise_error(Delayed::DeserializationError)
165
+ describe 'payload_object' do
166
+ it 'raises a DeserializationError when the job class is totally unknown' do
167
+ job = described_class.new :handler => '--- !ruby/object:JobThatDoesNotExist {}'
168
+ expect { job.payload_object }.to raise_error(Delayed::DeserializationError)
169
169
  end
170
170
 
171
- it "raises a DeserializationError when the job struct is totally unknown" do
172
- job = described_class.new :handler => "--- !ruby/struct:StructThatDoesNotExist {}"
173
- expect{job.payload_object}.to raise_error(Delayed::DeserializationError)
171
+ it 'raises a DeserializationError when the job struct is totally unknown' do
172
+ job = described_class.new :handler => '--- !ruby/struct:StructThatDoesNotExist {}'
173
+ expect { job.payload_object }.to raise_error(Delayed::DeserializationError)
174
174
  end
175
175
 
176
- it "raises a DeserializationError when the YAML.load raises argument error" do
177
- job = described_class.new :handler => "--- !ruby/struct:GoingToRaiseArgError {}"
176
+ it 'raises a DeserializationError when the YAML.load raises argument error' do
177
+ job = described_class.new :handler => '--- !ruby/struct:GoingToRaiseArgError {}'
178
178
  expect(YAML).to receive(:load).and_raise(ArgumentError)
179
- expect{job.payload_object}.to raise_error(Delayed::DeserializationError)
179
+ expect { job.payload_object }.to raise_error(Delayed::DeserializationError)
180
180
  end
181
181
  end
182
182
 
183
- describe "reserve" do
183
+ describe 'reserve' do
184
184
  before do
185
185
  Delayed::Worker.max_run_time = 2.minutes
186
186
  end
@@ -189,28 +189,28 @@ shared_examples_for "a delayed_job backend" do
189
189
  Time.zone = nil
190
190
  end
191
191
 
192
- it "does not reserve failed jobs" do
192
+ it 'does not reserve failed jobs' do
193
193
  create_job :attempts => 50, :failed_at => described_class.db_time_now
194
194
  expect(described_class.reserve(worker)).to be_nil
195
195
  end
196
196
 
197
- it "does not reserve jobs scheduled for the future" do
197
+ it 'does not reserve jobs scheduled for the future' do
198
198
  create_job :run_at => described_class.db_time_now + 1.minute
199
199
  expect(described_class.reserve(worker)).to be_nil
200
200
  end
201
201
 
202
- it "reserves jobs scheduled for the past" do
202
+ it 'reserves jobs scheduled for the past' do
203
203
  job = create_job :run_at => described_class.db_time_now - 1.minute
204
204
  expect(described_class.reserve(worker)).to eq(job)
205
205
  end
206
206
 
207
- it "reserves jobs scheduled for the past when time zones are involved" do
207
+ it 'reserves jobs scheduled for the past when time zones are involved' do
208
208
  Time.zone = 'US/Eastern'
209
209
  job = create_job :run_at => described_class.db_time_now - 1.minute
210
210
  expect(described_class.reserve(worker)).to eq(job)
211
211
  end
212
212
 
213
- it "does not reserve jobs locked by other workers" do
213
+ it 'does not reserve jobs locked by other workers' do
214
214
  job = create_job
215
215
  other_worker = Delayed::Worker.new
216
216
  other_worker.name = 'other_worker'
@@ -218,51 +218,51 @@ shared_examples_for "a delayed_job backend" do
218
218
  expect(described_class.reserve(worker)).to be_nil
219
219
  end
220
220
 
221
- it "reserves open jobs" do
221
+ it 'reserves open jobs' do
222
222
  job = create_job
223
223
  expect(described_class.reserve(worker)).to eq(job)
224
224
  end
225
225
 
226
- it "reserves expired jobs" do
226
+ it 'reserves expired jobs' do
227
227
  job = create_job(:locked_by => 'some other worker', :locked_at => described_class.db_time_now - Delayed::Worker.max_run_time - 1.minute)
228
228
  expect(described_class.reserve(worker)).to eq(job)
229
229
  end
230
230
 
231
- it "reserves own jobs" do
231
+ it 'reserves own jobs' do
232
232
  job = create_job(:locked_by => worker.name, :locked_at => (described_class.db_time_now - 1.minutes))
233
233
  expect(described_class.reserve(worker)).to eq(job)
234
234
  end
235
235
  end
236
236
 
237
- context "#name" do
238
- it "is the class name of the job that was enqueued" do
239
- expect(described_class.create(:payload_object => ErrorJob.new ).name).to eq('ErrorJob')
237
+ context '#name' do
238
+ it 'is the class name of the job that was enqueued' do
239
+ expect(described_class.create(:payload_object => ErrorJob.new).name).to eq('ErrorJob')
240
240
  end
241
241
 
242
- it "is the method that will be called if its a performable method object" do
242
+ it 'is the method that will be called if its a performable method object' do
243
243
  job = described_class.new(:payload_object => NamedJob.new)
244
244
  expect(job.name).to eq('named_job')
245
245
  end
246
246
 
247
- it "is the instance method that will be called if its a performable method object" do
248
- job = Story.create(:text => "...").delay.save
247
+ it 'is the instance method that will be called if its a performable method object' do
248
+ job = Story.create(:text => '...').delay.save
249
249
  expect(job.name).to eq('Story#save')
250
250
  end
251
251
 
252
- it "parses from handler on deserialization error" do
253
- job = Story.create(:text => "...").delay.text
252
+ it 'parses from handler on deserialization error' do
253
+ job = Story.create(:text => '...').delay.text
254
254
  job.payload_object.object.destroy
255
255
  expect(job.reload.name).to eq('Delayed::PerformableMethod')
256
256
  end
257
257
  end
258
258
 
259
- context "worker prioritization" do
259
+ context 'worker prioritization' do
260
260
  after do
261
261
  Delayed::Worker.max_priority = nil
262
262
  Delayed::Worker.min_priority = nil
263
263
  end
264
264
 
265
- it "fetches jobs ordered by priority" do
265
+ it 'fetches jobs ordered by priority' do
266
266
  10.times { described_class.enqueue SimpleJob.new, :priority => rand(10) }
267
267
  jobs = []
268
268
  10.times { jobs << described_class.reserve(worker) }
@@ -272,10 +272,10 @@ shared_examples_for "a delayed_job backend" do
272
272
  end
273
273
  end
274
274
 
275
- it "only finds jobs greater than or equal to min priority" do
275
+ it 'only finds jobs greater than or equal to min priority' do
276
276
  min = 5
277
277
  Delayed::Worker.min_priority = min
278
- [4,5,6].sort_by {|i| rand }.each {|i| create_job :priority => i }
278
+ [4, 5, 6].sort_by { |_i| rand }.each { |i| create_job :priority => i }
279
279
  2.times do
280
280
  job = described_class.reserve(worker)
281
281
  expect(job.priority).to be >= min
@@ -284,10 +284,10 @@ shared_examples_for "a delayed_job backend" do
284
284
  expect(described_class.reserve(worker)).to be_nil
285
285
  end
286
286
 
287
- it "only finds jobs less than or equal to max priority" do
287
+ it 'only finds jobs less than or equal to max priority' do
288
288
  max = 5
289
289
  Delayed::Worker.max_priority = max
290
- [4,5,6].sort_by {|i| rand }.each {|i| create_job :priority => i }
290
+ [4, 5, 6].sort_by { |_i| rand }.each { |i| create_job :priority => i }
291
291
  2.times do
292
292
  job = described_class.reserve(worker)
293
293
  expect(job.priority).to be <= max
@@ -297,73 +297,73 @@ shared_examples_for "a delayed_job backend" do
297
297
  end
298
298
  end
299
299
 
300
- context "clear_locks!" do
300
+ context 'clear_locks!' do
301
301
  before do
302
302
  @job = create_job(:locked_by => 'worker1', :locked_at => described_class.db_time_now)
303
303
  end
304
304
 
305
- it "clears locks for the given worker" do
305
+ it 'clears locks for the given worker' do
306
306
  described_class.clear_locks!('worker1')
307
307
  expect(described_class.reserve(worker)).to eq(@job)
308
308
  end
309
309
 
310
- it "does not clear locks for other workers" do
310
+ it 'does not clear locks for other workers' do
311
311
  described_class.clear_locks!('different_worker')
312
312
  expect(described_class.reserve(worker)).not_to eq(@job)
313
313
  end
314
314
  end
315
315
 
316
- context "unlock" do
316
+ context 'unlock' do
317
317
  before do
318
318
  @job = create_job(:locked_by => 'worker', :locked_at => described_class.db_time_now)
319
319
  end
320
320
 
321
- it "clears locks" do
321
+ it 'clears locks' do
322
322
  @job.unlock
323
323
  expect(@job.locked_by).to be_nil
324
324
  expect(@job.locked_at).to be_nil
325
325
  end
326
326
  end
327
327
 
328
- context "large handler" do
328
+ context 'large handler' do
329
329
  before do
330
- text = "Lorem ipsum dolor sit amet. " * 1000
330
+ text = 'Lorem ipsum dolor sit amet. ' * 1000
331
331
  @job = described_class.enqueue Delayed::PerformableMethod.new(text, :length, {})
332
332
  end
333
333
 
334
- it "has an id" do
334
+ it 'has an id' do
335
335
  expect(@job.id).not_to be_nil
336
336
  end
337
337
  end
338
338
 
339
- context "named queues" do
340
- context "when worker has one queue set" do
339
+ context 'named queues' do
340
+ context 'when worker has one queue set' do
341
341
  before(:each) do
342
342
  worker.queues = ['large']
343
343
  end
344
344
 
345
- it "only works off jobs which are from its queue" do
345
+ it 'only works off jobs which are from its queue' do
346
346
  expect(SimpleJob.runs).to eq(0)
347
347
 
348
- create_job(:queue => "large")
349
- create_job(:queue => "small")
348
+ create_job(:queue => 'large')
349
+ create_job(:queue => 'small')
350
350
  worker.work_off
351
351
 
352
352
  expect(SimpleJob.runs).to eq(1)
353
353
  end
354
354
  end
355
355
 
356
- context "when worker has two queue set" do
356
+ context 'when worker has two queue set' do
357
357
  before(:each) do
358
- worker.queues = ['large', 'small']
358
+ worker.queues = %w[large small]
359
359
  end
360
360
 
361
- it "only works off jobs which are from its queue" do
361
+ it 'only works off jobs which are from its queue' do
362
362
  expect(SimpleJob.runs).to eq(0)
363
363
 
364
- create_job(:queue => "large")
365
- create_job(:queue => "small")
366
- create_job(:queue => "medium")
364
+ create_job(:queue => 'large')
365
+ create_job(:queue => 'small')
366
+ create_job(:queue => 'medium')
367
367
  create_job
368
368
  worker.work_off
369
369
 
@@ -371,16 +371,16 @@ shared_examples_for "a delayed_job backend" do
371
371
  end
372
372
  end
373
373
 
374
- context "when worker does not have queue set" do
374
+ context 'when worker does not have queue set' do
375
375
  before(:each) do
376
376
  worker.queues = []
377
377
  end
378
378
 
379
- it "works off all jobs" do
379
+ it 'works off all jobs' do
380
380
  expect(SimpleJob.runs).to eq(0)
381
381
 
382
- create_job(:queue => "one")
383
- create_job(:queue => "two")
382
+ create_job(:queue => 'one')
383
+ create_job(:queue => 'two')
384
384
  create_job
385
385
  worker.work_off
386
386
 
@@ -389,84 +389,78 @@ shared_examples_for "a delayed_job backend" do
389
389
  end
390
390
  end
391
391
 
392
- context "max_attempts" do
392
+ context 'max_attempts' do
393
393
  before(:each) do
394
394
  @job = described_class.enqueue SimpleJob.new
395
395
  end
396
396
 
397
- it "is not defined" do
397
+ it 'is not defined' do
398
398
  expect(@job.max_attempts).to be_nil
399
399
  end
400
400
 
401
- it "uses the max_retries value on the payload when defined" do
401
+ it 'uses the max_retries value on the payload when defined' do
402
402
  expect(@job.payload_object).to receive(:max_attempts).and_return(99)
403
403
  expect(@job.max_attempts).to eq(99)
404
404
  end
405
405
  end
406
406
 
407
- describe "yaml serialization" do
408
- context "when serializing jobs" do
409
- it "raises error ArgumentError for new records" do
407
+ describe 'yaml serialization' do
408
+ context 'when serializing jobs' do
409
+ it 'raises error ArgumentError for new records' do
410
410
  story = Story.new(:text => 'hello')
411
411
  if story.respond_to?(:new_record?)
412
- expect {
413
- story.delay.tell
414
- }.to raise_error(ArgumentError, 'Jobs cannot be created for non-persisted records')
412
+ expect { story.delay.tell }.to raise_error(ArgumentError, 'Jobs cannot be created for non-persisted records')
415
413
  end
416
414
  end
417
415
 
418
- it "raises error ArgumentError for destroyed records" do
416
+ it 'raises error ArgumentError for destroyed records' do
419
417
  story = Story.create(:text => 'hello')
420
418
  story.destroy
421
- expect {
422
- story.delay.tell
423
- }.to raise_error(ArgumentError, 'Jobs cannot be created for non-persisted records')
419
+ expect { story.delay.tell }.to raise_error(ArgumentError, 'Jobs cannot be created for non-persisted records')
424
420
  end
425
421
  end
426
422
 
427
- context "when reload jobs back" do
428
- it "reloads changed attributes" do
423
+ context 'when reload jobs back' do
424
+ it 'reloads changed attributes' do
429
425
  story = Story.create(:text => 'hello')
430
426
  job = story.delay.tell
431
427
  story.update_attributes :text => 'goodbye'
432
428
  expect(job.reload.payload_object.object.text).to eq('goodbye')
433
429
  end
434
430
 
435
- it "raises deserialization error for destroyed records" do
431
+ it 'raises deserialization error for destroyed records' do
436
432
  story = Story.create(:text => 'hello')
437
433
  job = story.delay.tell
438
434
  story.destroy
439
- expect {
440
- job.reload.payload_object
441
- }.to raise_error(Delayed::DeserializationError)
435
+ expect { job.reload.payload_object }.to raise_error(Delayed::DeserializationError)
442
436
  end
443
437
  end
444
438
  end
445
439
 
446
- describe "worker integration" do
440
+ describe 'worker integration' do
447
441
  before do
448
442
  Delayed::Job.delete_all
449
443
  SimpleJob.runs = 0
450
444
  end
451
445
 
452
- describe "running a job" do
453
- it "fails after Worker.max_run_time" do
446
+ describe 'running a job' do
447
+ it 'fails after Worker.max_run_time' do
454
448
  Delayed::Worker.max_run_time = 1.second
455
449
  job = Delayed::Job.create :payload_object => LongRunningJob.new
456
450
  worker.run(job)
457
451
  expect(job.reload.last_error).to match(/expired/)
458
- expect(job.reload.last_error).to match(/Delayed::Worker.max_run_time is only 1 second/)
452
+ expect(job.reload.last_error).to match(/Delayed::Worker\.max_run_time is only 1 second/)
459
453
  expect(job.attempts).to eq(1)
460
454
  end
461
455
 
462
- context "when the job raises a deserialization error" do
456
+ context 'when the job raises a deserialization error' do
463
457
  after do
464
458
  Delayed::Worker.destroy_failed_jobs = true
465
459
  end
466
460
 
467
- it "marks the job as failed" do
461
+ it 'marks the job as failed' do
468
462
  Delayed::Worker.destroy_failed_jobs = false
469
- job = described_class.create! :handler => "--- !ruby/object:JobThatDoesNotExist {}"
463
+ job = described_class.create! :handler => '--- !ruby/object:JobThatDoesNotExist {}'
470
464
  worker.work_off
471
465
  job.reload
472
466
  expect(job).to be_failed
@@ -474,7 +468,7 @@ shared_examples_for "a delayed_job backend" do
474
468
  end
475
469
  end
476
470
 
477
- describe "failed jobs" do
471
+ describe 'failed jobs' do
478
472
  before do
479
473
  @job = Delayed::Job.enqueue(ErrorJob.new, :run_at => described_class.db_time_now - 1)
480
474
  end
@@ -484,7 +478,7 @@ shared_examples_for "a delayed_job backend" do
484
478
  Delayed::Worker.destroy_failed_jobs = true
485
479
  end
486
480
 
487
- it "records last_error when destroy_failed_jobs = false, max_attempts = 1" do
481
+ it 'records last_error when destroy_failed_jobs = false, max_attempts = 1' do
488
482
  Delayed::Worker.destroy_failed_jobs = false
489
483
  Delayed::Worker.max_attempts = 1
490
484
  worker.run(@job)
@@ -494,7 +488,7 @@ shared_examples_for "a delayed_job backend" do
494
488
  expect(@job).to be_failed
495
489
  end
496
490
 
497
- it "re-schedules jobs after failing" do
491
+ it 're-schedules jobs after failing' do
498
492
  worker.work_off
499
493
  @job.reload
500
494
  expect(@job.last_error).to match(/did not work/)
@@ -506,7 +500,7 @@ shared_examples_for "a delayed_job backend" do
506
500
  expect(@job.locked_at).to be_nil
507
501
  end
508
502
 
509
- it "re-schedules jobs with handler provided time if present" do
503
+ it 're-schedules jobs with handler provided time if present' do
510
504
  job = Delayed::Job.enqueue(CustomRescheduleJob.new(99.minutes))
511
505
  worker.run(job)
512
506
  job.reload
@@ -518,26 +512,33 @@ shared_examples_for "a delayed_job backend" do
518
512
  error_with_nil_message = StandardError.new
519
513
  expect(error_with_nil_message).to receive(:message).twice.and_return(nil)
520
514
  expect(@job).to receive(:invoke_job).and_raise error_with_nil_message
521
- expect{worker.run(@job)}.not_to raise_error
515
+ expect { worker.run(@job) }.not_to raise_error
522
516
  end
523
517
  end
524
518
 
525
- context "reschedule" do
519
+ context 'reschedule' do
526
520
  before do
527
521
  @job = Delayed::Job.create :payload_object => SimpleJob.new
528
522
  end
529
523
 
530
- shared_examples_for "any failure more than Worker.max_attempts times" do
524
+ shared_examples_for 'any failure more than Worker.max_attempts times' do
531
525
  context "when the job's payload has a #failure hook" do
532
526
  before do
533
527
  @job = Delayed::Job.create :payload_object => OnPermanentFailureJob.new
534
528
  expect(@job.payload_object).to respond_to(:failure)
535
529
  end
536
530
 
537
- it "runs that hook" do
531
+ it 'runs that hook' do
538
532
  expect(@job.payload_object).to receive(:failure)
539
533
  worker.reschedule(@job)
540
534
  end
535
+
536
+ it 'handles error in hook' do
537
+ Delayed::Worker.destroy_failed_jobs = false
538
+ @job.payload_object.raise_error = true
539
+ expect { worker.reschedule(@job) }.not_to raise_error
540
+ expect(@job.failed_at).to_not be_nil
541
+ end
541
542
  end
542
543
 
543
544
  context "when the job's payload has no #failure hook" do
@@ -555,23 +556,23 @@ shared_examples_for "a delayed_job backend" do
555
556
  expect(@job.payload_object).not_to respond_to(:failure)
556
557
  end
557
558
 
558
- it "does not try to run that hook" do
559
- expect {
559
+ it 'does not try to run that hook' do
560
+ expect do
560
561
  Delayed::Worker.max_attempts.times { worker.reschedule(@job) }
561
- }.not_to raise_exception
562
+ end.not_to raise_exception
562
563
  end
563
564
  end
564
565
  end
565
566
 
566
- context "and we want to destroy jobs" do
567
- it_should_behave_like "any failure more than Worker.max_attempts times"
567
+ context 'and we want to destroy jobs' do
568
+ it_behaves_like 'any failure more than Worker.max_attempts times'
568
569
 
569
- it "is destroyed if it failed more than Worker.max_attempts times" do
570
+ it 'is destroyed if it failed more than Worker.max_attempts times' do
570
571
  expect(@job).to receive(:destroy)
571
572
  Delayed::Worker.max_attempts.times { worker.reschedule(@job) }
572
573
  end
573
574
 
574
- it "is not destroyed if failed fewer than Worker.max_attempts times" do
575
+ it 'is not destroyed if failed fewer than Worker.max_attempts times' do
575
576
  expect(@job).not_to receive(:destroy)
576
577
  (Delayed::Worker.max_attempts - 1).times { worker.reschedule(@job) }
577
578
  end
@@ -586,15 +587,15 @@ shared_examples_for "a delayed_job backend" do
586
587
  Delayed::Worker.destroy_failed_jobs = true
587
588
  end
588
589
 
589
- it_should_behave_like "any failure more than Worker.max_attempts times"
590
+ it_behaves_like 'any failure more than Worker.max_attempts times'
590
591
 
591
- it "is failed if it failed more than Worker.max_attempts times" do
592
+ it 'is failed if it failed more than Worker.max_attempts times' do
592
593
  expect(@job.reload).not_to be_failed
593
594
  Delayed::Worker.max_attempts.times { worker.reschedule(@job) }
594
595
  expect(@job.reload).to be_failed
595
596
  end
596
597
 
597
- it "is not failed if it failed fewer than Worker.max_attempts times" do
598
+ it 'is not failed if it failed fewer than Worker.max_attempts times' do
598
599
  (Delayed::Worker.max_attempts - 1).times { worker.reschedule(@job) }
599
600
  expect(@job.reload).not_to be_failed
600
601
  end