delayed_job 4.1.2 → 4.1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +39 -0
- data/README.md +31 -21
- data/delayed_job.gemspec +7 -2
- data/lib/delayed/backend/base.rb +6 -8
- data/lib/delayed/backend/job_preparer.rb +3 -1
- data/lib/delayed/backend/shared_spec.rb +8 -1
- data/lib/delayed/command.rb +6 -1
- data/lib/delayed/exceptions.rb +1 -1
- data/lib/delayed/lifecycle.rb +1 -1
- data/lib/delayed/message_sending.rb +27 -25
- data/lib/delayed/performable_method.rb +2 -0
- data/lib/delayed/psych_ext.rb +16 -3
- data/lib/delayed/railtie.rb +0 -4
- data/lib/delayed/serialization/active_record.rb +1 -1
- data/lib/delayed/syck_ext.rb +2 -2
- data/lib/delayed/worker.rb +14 -4
- data/lib/delayed_job.rb +12 -7
- data/lib/generators/delayed_job/delayed_job_generator.rb +1 -1
- data/spec/autoloaded/clazz.rb +1 -2
- data/spec/autoloaded/instance_clazz.rb +1 -2
- data/spec/autoloaded/instance_struct.rb +1 -2
- data/spec/autoloaded/struct.rb +1 -2
- data/spec/delayed/backend/test.rb +0 -5
- data/spec/helper.rb +11 -9
- data/spec/message_sending_spec.rb +9 -5
- data/spec/performable_mailer_spec.rb +26 -1
- data/spec/performable_method_spec.rb +1 -2
- data/spec/psych_ext_spec.rb +23 -1
- data/spec/worker_spec.rb +9 -1
- metadata +19 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2c2e880a669ae56ceb7d75aa435f7a24540f3ff1669d5f0513eb82d7418cbcb5
|
4
|
+
data.tar.gz: aa5972d6556772c30eae6bff54bfa6fe02216d532af37d780f4da58c3beff702
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: edc7f370dc4f2783ada28648641be2274fee0adc260d2f4f230a999884850c5cff6aa5086b5df56c0be288ac23dd9edc997b48dc24b378ab8b8c99bf9e74107f
|
7
|
+
data.tar.gz: 3e5162db607ddf2d9b35c4a931deea4dfd494a683730652b14d067b911717c4bb8484205cec85190c7a695dba01ef68d405e6070ec961471fd9c32630c0e352c
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,43 @@
|
|
1
|
+
4.1.9 - 2020-12-09
|
2
|
+
==================
|
3
|
+
* Support for Rails 6.1
|
4
|
+
* Add support for parameterized mailers via delay call (#1121)
|
5
|
+
|
6
|
+
4.1.8 - 2019-08-16
|
7
|
+
==================
|
8
|
+
* Support for Rails 6.0.0
|
9
|
+
|
10
|
+
4.1.7 - 2019-06-20
|
11
|
+
==================
|
12
|
+
* Fix loading Delayed::PerformableMailer when ActionMailer isn't loaded yet
|
13
|
+
|
14
|
+
4.1.6 - 2019-06-19
|
15
|
+
==================
|
16
|
+
* Properly initialize ActionMailer outside railties (#1077)
|
17
|
+
* Fix Psych load_tags support (#1093)
|
18
|
+
* Replace REMOVED with FAILED in log message (#1048)
|
19
|
+
* Misc doc updates (#1052, #1074, #1064, #1063)
|
20
|
+
|
21
|
+
4.1.5 - 2018-04-13
|
22
|
+
==================
|
23
|
+
* Allow Rails 5.2
|
24
|
+
|
25
|
+
4.1.4 - 2017-12-29
|
26
|
+
==================
|
27
|
+
* Use `yaml_tag` instead of deprecated `yaml_as` (#996)
|
28
|
+
* Support ruby 2.5.0
|
29
|
+
|
30
|
+
4.1.3 - 2017-05-26
|
31
|
+
==================
|
32
|
+
* Don't mutate the options hash (#877)
|
33
|
+
* Log an error message when a deserialization error occurs (#894)
|
34
|
+
* Adding the queue name to the log output (#917)
|
35
|
+
* Don't include ClassMethods with MessageSending (#924)
|
36
|
+
* Fix YAML deserialization error if original object is soft-deleted (#947)
|
37
|
+
* Add support for Rails 5.1 (#982)
|
38
|
+
|
1
39
|
4.1.2 - 2016-05-16
|
40
|
+
==================
|
2
41
|
* Added Delayed::Worker.queue_attributes
|
3
42
|
* Limit what we require in ActiveSupport
|
4
43
|
* Fix pid file creation when there is no tmp directory
|
data/README.md
CHANGED
@@ -1,19 +1,16 @@
|
|
1
1
|
**If you're viewing this at https://github.com/collectiveidea/delayed_job,
|
2
2
|
you're reading the documentation for the master branch.
|
3
3
|
[View documentation for the latest release
|
4
|
-
(4.1.
|
4
|
+
(4.1.9).](https://github.com/collectiveidea/delayed_job/tree/v4.1.9)**
|
5
5
|
|
6
6
|
Delayed::Job
|
7
7
|
============
|
8
|
-
[![Gem Version](https://badge.fury.io/rb/delayed_job.
|
9
|
-
|
10
|
-
[![
|
11
|
-
[![
|
12
|
-
[![Coverage Status](https://coveralls.io/repos/collectiveidea/delayed_job/badge.png?branch=master)][coveralls]
|
8
|
+
[![Gem Version](https://badge.fury.io/rb/delayed_job.svg)][gem]
|
9
|
+
![CI](https://github.com/collectiveidea/delayed_job/workflows/CI/badge.svg)
|
10
|
+
[![Code Climate](https://codeclimate.com/github/collectiveidea/delayed_job.svg)][codeclimate]
|
11
|
+
[![Coverage Status](https://coveralls.io/repos/collectiveidea/delayed_job/badge.svg?branch=master)][coveralls]
|
13
12
|
|
14
13
|
[gem]: https://rubygems.org/gems/delayed_job
|
15
|
-
[travis]: https://travis-ci.org/collectiveidea/delayed_job
|
16
|
-
[gemnasium]: https://gemnasium.com/collectiveidea/delayed_job
|
17
14
|
[codeclimate]: https://codeclimate.com/github/collectiveidea/delayed_job
|
18
15
|
[coveralls]: https://coveralls.io/r/collectiveidea/delayed_job
|
19
16
|
|
@@ -37,8 +34,7 @@ multitude of core tasks. Amongst those tasks are:
|
|
37
34
|
|
38
35
|
Installation
|
39
36
|
============
|
40
|
-
delayed_job 3.0.0 only supports Rails 3.0+.
|
41
|
-
branch](https://github.com/collectiveidea/delayed_job/tree/v2.0) for Rails 2.
|
37
|
+
delayed_job 3.0.0 only supports Rails 3.0+.
|
42
38
|
|
43
39
|
delayed_job supports multiple backends for storing the job queue. [See the wiki
|
44
40
|
for other backends](https://github.com/collectiveidea/delayed_job/wiki/Backends).
|
@@ -63,16 +59,16 @@ running the following command:
|
|
63
59
|
rails generate delayed_job:active_record
|
64
60
|
rake db:migrate
|
65
61
|
|
66
|
-
For Rails 4.2
|
62
|
+
For Rails 4.2+, see [below](#active-job)
|
67
63
|
|
68
64
|
Development
|
69
65
|
===========
|
70
66
|
In development mode, if you are using Rails 3.1+, your application code will automatically reload every 100 jobs or when the queue finishes.
|
71
67
|
You no longer need to restart Delayed Job every time you update your code in development.
|
72
68
|
|
73
|
-
|
74
|
-
|
75
|
-
|
69
|
+
Active Job
|
70
|
+
==========
|
71
|
+
In Rails 4.2+, set the queue_adapter in config/application.rb
|
76
72
|
|
77
73
|
```ruby
|
78
74
|
config.active_job.queue_adapter = :delayed_job
|
@@ -171,9 +167,10 @@ end
|
|
171
167
|
|
172
168
|
If you ever want to call a `handle_asynchronously`'d method without Delayed Job, for instance while debugging something at the console, just add `_without_delay` to the method name. For instance, if your original method was `foo`, then call `foo_without_delay`.
|
173
169
|
|
174
|
-
Rails
|
175
|
-
|
176
|
-
|
170
|
+
Rails Mailers
|
171
|
+
=============
|
172
|
+
Delayed Job uses special syntax for Rails Mailers.
|
173
|
+
Do not call the `.deliver` method when using `.delay`.
|
177
174
|
|
178
175
|
```ruby
|
179
176
|
# without delayed_job
|
@@ -182,12 +179,16 @@ Notifier.signup(@user).deliver
|
|
182
179
|
# with delayed_job
|
183
180
|
Notifier.delay.signup(@user)
|
184
181
|
|
185
|
-
#
|
182
|
+
# delayed_job running at a specific time
|
186
183
|
Notifier.delay(run_at: 5.minutes.from_now).signup(@user)
|
184
|
+
|
185
|
+
# when using parameters, the .with method must be called before the .delay method
|
186
|
+
Notifier.with(foo: 1, bar: 2).delay.signup(@user)
|
187
187
|
```
|
188
188
|
|
189
|
-
|
190
|
-
|
189
|
+
You may also wish to consider using
|
190
|
+
[Active Job with Action Mailer](https://edgeguides.rubyonrails.org/active_job_basics.html#action-mailer)
|
191
|
+
which provides convenient `.deliver_later` syntax that forwards to Delayed Job under-the-hood.
|
191
192
|
|
192
193
|
Named Queues
|
193
194
|
============
|
@@ -220,6 +221,12 @@ Configured queue priorities can be overriden by passing priority to the delay me
|
|
220
221
|
object.delay(:queue => 'high_priority', priority: 0).method
|
221
222
|
```
|
222
223
|
|
224
|
+
You can start processes to only work certain queues with the `queue` and `queues`
|
225
|
+
options defined below. Processes started without specifying a queue will run jobs
|
226
|
+
from **any** queue. To effectively have a process that runs jobs where a queue is not
|
227
|
+
specified, set a default queue name with `Delayed::Worker.default_queue_name` and
|
228
|
+
have the processes run that queue.
|
229
|
+
|
223
230
|
Running Jobs
|
224
231
|
============
|
225
232
|
`script/delayed_job` can be used to manage a background process which will
|
@@ -372,6 +379,9 @@ Hooks
|
|
372
379
|
=====
|
373
380
|
You can define hooks on your job that will be called at different stages in the process:
|
374
381
|
|
382
|
+
|
383
|
+
**NOTE:** If you are using ActiveJob these hooks are **not** available to your jobs. You will need to use ActiveJob's callbacks. You can find details here https://guides.rubyonrails.org/active_job_basics.html#callbacks
|
384
|
+
|
375
385
|
```ruby
|
376
386
|
class ParanoidNewsletterJob < NewsletterJob
|
377
387
|
def enqueue(job)
|
@@ -425,7 +435,7 @@ end
|
|
425
435
|
|
426
436
|
On error, the job is scheduled again in 5 seconds + N ** 4, where N is the number of attempts or using the job's defined `reschedule_at` method.
|
427
437
|
|
428
|
-
The default `Worker.max_attempts` is 25. After this, the job either deleted (default), or left in the database with "failed_at" set.
|
438
|
+
The default `Worker.max_attempts` is 25. After this, the job is either deleted (default), or left in the database with "failed_at" set.
|
429
439
|
With the default of 25 attempts, the last retry will be 20 days later, with the last interval being almost 100 hours.
|
430
440
|
|
431
441
|
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
|
data/delayed_job.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
|
-
spec.add_dependency 'activesupport', ['>= 3.0', '<
|
4
|
+
spec.add_dependency 'activesupport', ['>= 3.0', '< 6.2']
|
5
5
|
spec.authors = ['Brandon Keepers', 'Brian Ryckbost', 'Chris Gaffney', 'David Genord II', 'Erik Michaels-Ober', 'Matt Griffin', 'Steve Richert', 'Tobias Lütke']
|
6
6
|
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.'
|
7
7
|
spec.email = ['brian@collectiveidea.com']
|
@@ -13,5 +13,10 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.require_paths = ['lib']
|
14
14
|
spec.summary = 'Database-backed asynchronous priority queue system -- Extracted from Shopify'
|
15
15
|
spec.test_files = Dir.glob('spec/**/*')
|
16
|
-
spec.version = '4.1.
|
16
|
+
spec.version = '4.1.9'
|
17
|
+
spec.metadata = {
|
18
|
+
'changelog_uri' => 'https://github.com/collectiveidea/delayed_job/blob/master/CHANGELOG.md',
|
19
|
+
'bug_tracker_uri' => 'https://github.com/collectiveidea/delayed_job/issues',
|
20
|
+
'source_code_uri' => 'https://github.com/collectiveidea/delayed_job'
|
21
|
+
}
|
17
22
|
end
|
data/lib/delayed/backend/base.rb
CHANGED
@@ -30,16 +30,13 @@ module Delayed
|
|
30
30
|
end
|
31
31
|
|
32
32
|
# Allow the backend to attempt recovery from reserve errors
|
33
|
-
def recover_from(_error)
|
34
|
-
end
|
33
|
+
def recover_from(_error); end
|
35
34
|
|
36
35
|
# Hook method that is called before a new worker is forked
|
37
|
-
def before_fork
|
38
|
-
end
|
36
|
+
def before_fork; end
|
39
37
|
|
40
38
|
# Hook method that is called after a new worker is forked
|
41
|
-
def after_fork
|
42
|
-
end
|
39
|
+
def after_fork; end
|
43
40
|
|
44
41
|
def work_off(num = 100)
|
45
42
|
warn '[DEPRECATION] `Delayed::Job.work_off` is deprecated. Use `Delayed::Worker.new.work_off instead.'
|
@@ -101,7 +98,7 @@ module Delayed
|
|
101
98
|
def hook(name, *args)
|
102
99
|
if payload_object.respond_to?(name)
|
103
100
|
method = payload_object.method(name)
|
104
|
-
method.arity
|
101
|
+
method.arity.zero? ? method.call : method.call(self, *args)
|
105
102
|
end
|
106
103
|
rescue DeserializationError # rubocop:disable HandleExceptions
|
107
104
|
end
|
@@ -136,7 +133,8 @@ module Delayed
|
|
136
133
|
end
|
137
134
|
|
138
135
|
def fail!
|
139
|
-
|
136
|
+
self.failed_at = self.class.db_time_now
|
137
|
+
save!
|
140
138
|
end
|
141
139
|
|
142
140
|
protected
|
@@ -4,7 +4,7 @@ module Delayed
|
|
4
4
|
attr_reader :options, :args
|
5
5
|
|
6
6
|
def initialize(*args)
|
7
|
-
@options = args.extract_options
|
7
|
+
@options = args.extract_options!.dup
|
8
8
|
@args = args
|
9
9
|
end
|
10
10
|
|
@@ -42,9 +42,11 @@ module Delayed
|
|
42
42
|
options[:run_at] = args[1]
|
43
43
|
end
|
44
44
|
|
45
|
+
# rubocop:disable GuardClause
|
45
46
|
unless options[:payload_object].respond_to?(:perform)
|
46
47
|
raise ArgumentError, 'Cannot enqueue items which do not respond to perform'
|
47
48
|
end
|
49
|
+
# rubocop:enabled GuardClause
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|
@@ -113,6 +113,12 @@ shared_examples_for 'a delayed_job backend' do
|
|
113
113
|
job = described_class.enqueue M::ModuleJob.new
|
114
114
|
expect { job.invoke_job }.to change { M::ModuleJob.runs }.from(0).to(1)
|
115
115
|
end
|
116
|
+
|
117
|
+
it 'does not mutate the options hash' do
|
118
|
+
options = {:priority => 1}
|
119
|
+
described_class.enqueue SimpleJob.new, options
|
120
|
+
expect(options).to eq(:priority => 1)
|
121
|
+
end
|
116
122
|
end
|
117
123
|
|
118
124
|
context 'with delay_jobs = false' do
|
@@ -517,7 +523,8 @@ shared_examples_for 'a delayed_job backend' do
|
|
517
523
|
it 'reloads changed attributes' do
|
518
524
|
story = Story.create(:text => 'hello')
|
519
525
|
job = story.delay.tell
|
520
|
-
story.
|
526
|
+
story.text = 'goodbye'
|
527
|
+
story.save!
|
521
528
|
expect(job.reload.payload_object.object.text).to eq('goodbye')
|
522
529
|
end
|
523
530
|
|
data/lib/delayed/command.rb
CHANGED
@@ -77,8 +77,11 @@ module Delayed
|
|
77
77
|
opt.on('--exit-on-complete', 'Exit when no more jobs are available to run. This will exit if all jobs are scheduled to run in the future.') do
|
78
78
|
@options[:exit_on_complete] = true
|
79
79
|
end
|
80
|
+
opt.on('--daemon-options a, b, c', Array, 'options to be passed through to daemons gem') do |daemon_options|
|
81
|
+
@daemon_options = daemon_options
|
82
|
+
end
|
80
83
|
end
|
81
|
-
@args = opts.parse!(args)
|
84
|
+
@args = opts.parse!(args) + (@daemon_options || [])
|
82
85
|
end
|
83
86
|
|
84
87
|
def daemonize # rubocop:disable PerceivedComplexity
|
@@ -88,11 +91,13 @@ module Delayed
|
|
88
91
|
if worker_pools
|
89
92
|
setup_pools
|
90
93
|
elsif @options[:identifier]
|
94
|
+
# rubocop:disable GuardClause
|
91
95
|
if worker_count > 1
|
92
96
|
raise ArgumentError, 'Cannot specify both --number-of-workers and --identifier'
|
93
97
|
else
|
94
98
|
run_process("delayed_job.#{@options[:identifier]}", @options)
|
95
99
|
end
|
100
|
+
# rubocop:enable GuardClause
|
96
101
|
else
|
97
102
|
worker_count.times do |worker_index|
|
98
103
|
process_name = worker_count == 1 ? 'delayed_job' : "delayed_job.#{worker_index}"
|
data/lib/delayed/exceptions.rb
CHANGED
data/lib/delayed/lifecycle.rb
CHANGED
@@ -6,9 +6,11 @@ module Delayed
|
|
6
6
|
@options = options
|
7
7
|
end
|
8
8
|
|
9
|
+
# rubocop:disable MethodMissing
|
9
10
|
def method_missing(method, *args)
|
10
11
|
Job.enqueue({:payload_object => @payload_class.new(@target, method.to_sym, args)}.merge(@options))
|
11
12
|
end
|
13
|
+
# rubocop:enable MethodMissing
|
12
14
|
end
|
13
15
|
|
14
16
|
module MessageSending
|
@@ -26,36 +28,36 @@ module Delayed
|
|
26
28
|
warn '[DEPRECATION] `object.send_at(time, :method)` is deprecated. Use `object.delay(:run_at => time).method'
|
27
29
|
__delay__(:run_at => time).__send__(method, *args)
|
28
30
|
end
|
31
|
+
end
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
33
|
+
module MessageSendingClassMethods
|
34
|
+
def handle_asynchronously(method, opts = {}) # rubocop:disable PerceivedComplexity
|
35
|
+
aliased_method = method.to_s.sub(/([?!=])$/, '')
|
36
|
+
punctuation = $1 # rubocop:disable PerlBackrefs
|
37
|
+
with_method = "#{aliased_method}_with_delay#{punctuation}"
|
38
|
+
without_method = "#{aliased_method}_without_delay#{punctuation}"
|
39
|
+
define_method(with_method) do |*args|
|
40
|
+
curr_opts = opts.clone
|
41
|
+
curr_opts.each_key do |key|
|
42
|
+
next unless (val = curr_opts[key]).is_a?(Proc)
|
43
|
+
curr_opts[key] = if val.arity == 1
|
44
|
+
val.call(self)
|
45
|
+
else
|
46
|
+
val.call
|
45
47
|
end
|
46
|
-
delay(curr_opts).__send__(without_method, *args)
|
47
48
|
end
|
49
|
+
delay(curr_opts).__send__(without_method, *args)
|
50
|
+
end
|
48
51
|
|
49
|
-
|
50
|
-
|
52
|
+
alias_method without_method, method
|
53
|
+
alias_method method, with_method
|
51
54
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
end
|
55
|
+
if public_method_defined?(without_method)
|
56
|
+
public method
|
57
|
+
elsif protected_method_defined?(without_method)
|
58
|
+
protected method
|
59
|
+
elsif private_method_defined?(without_method)
|
60
|
+
private method
|
59
61
|
end
|
60
62
|
end
|
61
63
|
end
|
@@ -30,9 +30,11 @@ module Delayed
|
|
30
30
|
object.method(sym)
|
31
31
|
end
|
32
32
|
|
33
|
+
# rubocop:disable MethodMissing
|
33
34
|
def method_missing(symbol, *args)
|
34
35
|
object.send(symbol, *args)
|
35
36
|
end
|
37
|
+
# rubocop:enable MethodMissing
|
36
38
|
|
37
39
|
def respond_to?(symbol, include_private = false)
|
38
40
|
super || object.respond_to?(symbol, include_private)
|
data/lib/delayed/psych_ext.rb
CHANGED
@@ -28,16 +28,22 @@ module Delayed
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def visit_Psych_Nodes_Mapping(object) # rubocop:disable CyclomaticComplexity, MethodName, PerceivedComplexity
|
31
|
-
|
31
|
+
klass = Psych.load_tags[object.tag]
|
32
|
+
if klass
|
33
|
+
# Implementation changed here https://github.com/ruby/psych/commit/2c644e184192975b261a81f486a04defa3172b3f
|
34
|
+
# load_tags used to have class values, now the values are strings
|
35
|
+
klass = resolve_class(klass) if klass.is_a?(String)
|
36
|
+
return revive(klass, object)
|
37
|
+
end
|
32
38
|
|
33
39
|
case object.tag
|
34
40
|
when %r{^!ruby/object}
|
35
41
|
result = super
|
36
|
-
if
|
42
|
+
if jruby_is_seriously_borked && result.is_a?(ActiveRecord::Base)
|
37
43
|
klass = result.class
|
38
44
|
id = result[klass.primary_key]
|
39
45
|
begin
|
40
|
-
klass.find(id)
|
46
|
+
klass.unscoped.find(id)
|
41
47
|
rescue ActiveRecord::RecordNotFound => error # rubocop:disable BlockNesting
|
42
48
|
raise Delayed::DeserializationError, "ActiveRecord::RecordNotFound, class: #{klass}, primary key: #{id} (#{error.message})"
|
43
49
|
end
|
@@ -78,6 +84,13 @@ module Delayed
|
|
78
84
|
end
|
79
85
|
end
|
80
86
|
|
87
|
+
# defined? is triggering something really messed up in
|
88
|
+
# jruby causing both the if AND else clauses to execute,
|
89
|
+
# however if the check is run here, everything is fine
|
90
|
+
def jruby_is_seriously_borked
|
91
|
+
defined?(ActiveRecord::Base)
|
92
|
+
end
|
93
|
+
|
81
94
|
def resolve_class(klass_name)
|
82
95
|
return nil if !klass_name || klass_name.empty?
|
83
96
|
klass_name.constantize
|
data/lib/delayed/railtie.rb
CHANGED
@@ -4,10 +4,6 @@ require 'rails'
|
|
4
4
|
module Delayed
|
5
5
|
class Railtie < Rails::Railtie
|
6
6
|
initializer :after_initialize do
|
7
|
-
ActiveSupport.on_load(:action_mailer) do
|
8
|
-
ActionMailer::Base.extend(Delayed::DelayMail)
|
9
|
-
end
|
10
|
-
|
11
7
|
Delayed::Worker.logger ||= if defined?(Rails)
|
12
8
|
Rails.logger
|
13
9
|
elsif defined?(RAILS_DEFAULT_LOGGER)
|
data/lib/delayed/syck_ext.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Module
|
2
|
-
|
2
|
+
yaml_tag 'tag:ruby.yaml.org,2002:module'
|
3
3
|
|
4
4
|
def self.yaml_new(_klass, _tag, val)
|
5
5
|
val.constantize
|
@@ -20,7 +20,7 @@ class Module
|
|
20
20
|
end
|
21
21
|
|
22
22
|
class Class
|
23
|
-
|
23
|
+
yaml_tag 'tag:ruby.yaml.org,2002:class'
|
24
24
|
remove_method :to_yaml if respond_to?(:to_yaml) && method(:to_yaml).owner == Class # use Module's to_yaml
|
25
25
|
end
|
26
26
|
|
data/lib/delayed/worker.rb
CHANGED
@@ -233,6 +233,8 @@ module Delayed
|
|
233
233
|
job_say job, format('COMPLETED after %.4f', runtime)
|
234
234
|
return true # did work
|
235
235
|
rescue DeserializationError => error
|
236
|
+
job_say job, "FAILED permanently with #{error.class.name}: #{error.message}", 'error'
|
237
|
+
|
236
238
|
job.error = error
|
237
239
|
failed(job)
|
238
240
|
rescue Exception => error # rubocop:disable RescueException
|
@@ -249,7 +251,7 @@ module Delayed
|
|
249
251
|
job.unlock
|
250
252
|
job.save!
|
251
253
|
else
|
252
|
-
job_say job, "
|
254
|
+
job_say job, "FAILED permanently because of #{job.attempts} consecutive failures", 'error'
|
253
255
|
failed(job)
|
254
256
|
end
|
255
257
|
end
|
@@ -268,7 +270,7 @@ module Delayed
|
|
268
270
|
end
|
269
271
|
|
270
272
|
def job_say(job, text, level = default_log_level)
|
271
|
-
text = "Job #{job.name} (id=#{job.id}) #{text}"
|
273
|
+
text = "Job #{job.name} (id=#{job.id})#{say_queue(job.queue)} #{text}"
|
272
274
|
say text, level
|
273
275
|
end
|
274
276
|
|
@@ -293,6 +295,10 @@ module Delayed
|
|
293
295
|
|
294
296
|
protected
|
295
297
|
|
298
|
+
def say_queue(queue)
|
299
|
+
" (queue=#{queue})" if queue
|
300
|
+
end
|
301
|
+
|
296
302
|
def handle_failed_job(job, error)
|
297
303
|
job.error = error
|
298
304
|
job_say job, "FAILED (#{job.attempts} prior attempts) with #{error.class.name}: #{error.message}", 'error'
|
@@ -320,8 +326,12 @@ module Delayed
|
|
320
326
|
|
321
327
|
def reload!
|
322
328
|
return unless self.class.reload_app?
|
323
|
-
|
324
|
-
|
329
|
+
if defined?(ActiveSupport::Reloader)
|
330
|
+
Rails.application.reloader.reload!
|
331
|
+
else
|
332
|
+
ActionDispatch::Reloader.cleanup!
|
333
|
+
ActionDispatch::Reloader.prepare!
|
334
|
+
end
|
325
335
|
end
|
326
336
|
end
|
327
337
|
end
|
data/lib/delayed_job.rb
CHANGED
@@ -1,13 +1,8 @@
|
|
1
|
+
require 'active_support'
|
1
2
|
require 'delayed/compatibility'
|
2
3
|
require 'delayed/exceptions'
|
3
4
|
require 'delayed/message_sending'
|
4
5
|
require 'delayed/performable_method'
|
5
|
-
|
6
|
-
if defined?(ActionMailer)
|
7
|
-
require 'action_mailer/version'
|
8
|
-
require 'delayed/performable_mailer'
|
9
|
-
end
|
10
|
-
|
11
6
|
require 'delayed/yaml_ext'
|
12
7
|
require 'delayed/lifecycle'
|
13
8
|
require 'delayed/plugin'
|
@@ -18,5 +13,15 @@ require 'delayed/worker'
|
|
18
13
|
require 'delayed/deserialization_error'
|
19
14
|
require 'delayed/railtie' if defined?(Rails::Railtie)
|
20
15
|
|
16
|
+
ActiveSupport.on_load(:action_mailer) do
|
17
|
+
require 'delayed/performable_mailer'
|
18
|
+
ActionMailer::Base.extend(Delayed::DelayMail)
|
19
|
+
ActionMailer::Parameterized::Mailer.include(Delayed::DelayMail) if defined?(ActionMailer::Parameterized::Mailer)
|
20
|
+
end
|
21
|
+
|
22
|
+
module Delayed
|
23
|
+
autoload :PerformableMailer, 'delayed/performable_mailer'
|
24
|
+
end
|
25
|
+
|
21
26
|
Object.send(:include, Delayed::MessageSending)
|
22
|
-
Module.send(:include, Delayed::
|
27
|
+
Module.send(:include, Delayed::MessageSendingClassMethods)
|
@@ -6,6 +6,6 @@ class DelayedJobGenerator < Rails::Generators::Base
|
|
6
6
|
|
7
7
|
def create_executable_file
|
8
8
|
template 'script', "#{Delayed::Compatibility.executable_prefix}/delayed_job"
|
9
|
-
chmod "#{Delayed::Compatibility.executable_prefix}/delayed_job",
|
9
|
+
chmod "#{Delayed::Compatibility.executable_prefix}/delayed_job", 0o755
|
10
10
|
end
|
11
11
|
end
|
data/spec/autoloaded/clazz.rb
CHANGED
data/spec/autoloaded/struct.rb
CHANGED
data/spec/helper.rb
CHANGED
@@ -1,20 +1,25 @@
|
|
1
1
|
require 'simplecov'
|
2
|
-
require '
|
2
|
+
require 'simplecov-lcov'
|
3
3
|
|
4
|
-
SimpleCov
|
4
|
+
SimpleCov::Formatter::LcovFormatter.config do |c|
|
5
|
+
c.report_with_single_file = true
|
6
|
+
c.single_report_path = 'coverage/lcov.info'
|
7
|
+
end
|
8
|
+
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new(
|
9
|
+
[
|
10
|
+
SimpleCov::Formatter::HTMLFormatter,
|
11
|
+
SimpleCov::Formatter::LcovFormatter
|
12
|
+
]
|
13
|
+
)
|
5
14
|
|
6
15
|
SimpleCov.start do
|
7
16
|
add_filter '/spec/'
|
8
|
-
# Each version of ruby and version of rails test different things
|
9
|
-
# This should probably just be removed.
|
10
|
-
minimum_coverage(85.0)
|
11
17
|
end
|
12
18
|
|
13
19
|
require 'logger'
|
14
20
|
require 'rspec'
|
15
21
|
|
16
22
|
require 'action_mailer'
|
17
|
-
require 'active_support/dependencies'
|
18
23
|
require 'active_record'
|
19
24
|
|
20
25
|
require 'delayed_job'
|
@@ -45,9 +50,6 @@ Delayed::Worker.backend = :test
|
|
45
50
|
# Add this directory so the ActiveSupport autoloading works
|
46
51
|
ActiveSupport::Dependencies.autoload_paths << File.dirname(__FILE__)
|
47
52
|
|
48
|
-
# Add this to simulate Railtie initializer being executed
|
49
|
-
ActionMailer::Base.extend(Delayed::DelayMail)
|
50
|
-
|
51
53
|
# Used to test interactions between DJ and an ORM
|
52
54
|
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
|
53
55
|
ActiveRecord::Base.logger = Delayed::Worker.logger
|
@@ -1,6 +1,11 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe Delayed::MessageSending do
|
4
|
+
it 'does not include ClassMethods along with MessageSending' do
|
5
|
+
expect { ClassMethods }.to raise_error(NameError)
|
6
|
+
expect(defined?(String::ClassMethods)).to eq(nil)
|
7
|
+
end
|
8
|
+
|
4
9
|
describe 'handle_asynchronously' do
|
5
10
|
class Story
|
6
11
|
def tell!(_arg); end
|
@@ -19,7 +24,7 @@ describe Delayed::MessageSending do
|
|
19
24
|
expect(job.payload_object.class).to eq(Delayed::PerformableMethod)
|
20
25
|
expect(job.payload_object.method_name).to eq(:tell_without_delay!)
|
21
26
|
expect(job.payload_object.args).to eq([1])
|
22
|
-
end.to
|
27
|
+
end.to(change { Delayed::Job.count })
|
23
28
|
end
|
24
29
|
|
25
30
|
describe 'with options' do
|
@@ -42,8 +47,7 @@ describe Delayed::MessageSending do
|
|
42
47
|
describe 'using a proc with parameters' do
|
43
48
|
class Yarn
|
44
49
|
attr_accessor :importance
|
45
|
-
def spin
|
46
|
-
end
|
50
|
+
def spin; end
|
47
51
|
handle_asynchronously :spin, :priority => proc { |y| y.importance }
|
48
52
|
end
|
49
53
|
|
@@ -107,7 +111,7 @@ describe Delayed::MessageSending do
|
|
107
111
|
expect do
|
108
112
|
fairy_tail.delay.tell
|
109
113
|
end.to change(fairy_tail, :happy_ending).from(nil).to(true)
|
110
|
-
end.not_to
|
114
|
+
end.not_to(change { Delayed::Job.count })
|
111
115
|
end
|
112
116
|
|
113
117
|
it 'does delay the job when delay_jobs is true' do
|
@@ -137,7 +141,7 @@ describe Delayed::MessageSending do
|
|
137
141
|
expect do
|
138
142
|
fairy_tail.delay.tell
|
139
143
|
end.to change(fairy_tail, :happy_ending).from(nil).to(true)
|
140
|
-
end.not_to
|
144
|
+
end.not_to(change { Delayed::Job.count })
|
141
145
|
end
|
142
146
|
end
|
143
147
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
-
require 'action_mailer'
|
4
3
|
class MyMailer < ActionMailer::Base
|
5
4
|
def signup(email)
|
6
5
|
mail :to => email, :subject => 'Delaying Emails', :from => 'delayedjob@example.com', :body => 'Delaying Emails Body'
|
@@ -41,3 +40,29 @@ describe ActionMailer::Base do
|
|
41
40
|
end
|
42
41
|
end
|
43
42
|
end
|
43
|
+
|
44
|
+
if defined?(ActionMailer::Parameterized::Mailer)
|
45
|
+
describe ActionMailer::Parameterized::Mailer do
|
46
|
+
describe 'delay' do
|
47
|
+
it 'enqueues a PerformableEmail job' do
|
48
|
+
expect do
|
49
|
+
job = MyMailer.with(:foo => 1, :bar => 2).delay.signup('john@example.com')
|
50
|
+
expect(job.payload_object.class).to eq(Delayed::PerformableMailer)
|
51
|
+
expect(job.payload_object.object.class).to eq(ActionMailer::Parameterized::Mailer)
|
52
|
+
expect(job.payload_object.object.instance_variable_get('@mailer')).to eq(MyMailer)
|
53
|
+
expect(job.payload_object.object.instance_variable_get('@params')).to eq(:foo => 1, :bar => 2)
|
54
|
+
expect(job.payload_object.method_name).to eq(:signup)
|
55
|
+
expect(job.payload_object.args).to eq(['john@example.com'])
|
56
|
+
end.to change { Delayed::Job.count }.by(1)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'delay on a mail object' do
|
61
|
+
it 'raises an exception' do
|
62
|
+
expect do
|
63
|
+
MyMailer.with(:foo => 1, :bar => 2).signup('john@example.com').delay
|
64
|
+
end.to raise_error(RuntimeError)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -30,8 +30,7 @@ describe Delayed::PerformableMethod do
|
|
30
30
|
|
31
31
|
it 'does not raise NoMethodError if target method is private' do
|
32
32
|
clazz = Class.new do
|
33
|
-
def private_method
|
34
|
-
end
|
33
|
+
def private_method; end
|
35
34
|
private :private_method
|
36
35
|
end
|
37
36
|
expect { Delayed::PerformableMethod.new(clazz.new, :private_method, []) }.not_to raise_error
|
data/spec/psych_ext_spec.rb
CHANGED
@@ -3,10 +3,32 @@ require 'helper'
|
|
3
3
|
describe 'Psych::Visitors::ToRuby', :if => defined?(Psych::Visitors::ToRuby) do
|
4
4
|
context BigDecimal do
|
5
5
|
it 'deserializes correctly' do
|
6
|
-
deserialized = YAML.
|
6
|
+
deserialized = YAML.load_dj("--- !ruby/object:BigDecimal 18:0.1337E2\n...\n")
|
7
7
|
|
8
8
|
expect(deserialized).to be_an_instance_of(BigDecimal)
|
9
9
|
expect(deserialized).to eq(BigDecimal('13.37'))
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
context 'load_tag handling' do
|
14
|
+
# This only broadly works in ruby 2.0 but will cleanly work through load_dj
|
15
|
+
# here because this class is so simple it only touches our extention
|
16
|
+
YAML.load_tags['!ruby/object:RenamedClass'] = SimpleJob
|
17
|
+
# This is how ruby 2.1 and newer works throughout the yaml handling
|
18
|
+
YAML.load_tags['!ruby/object:RenamedString'] = 'SimpleJob'
|
19
|
+
|
20
|
+
it 'deserializes class tag' do
|
21
|
+
deserialized = YAML.load_dj("--- !ruby/object:RenamedClass\ncheck: 12\n")
|
22
|
+
|
23
|
+
expect(deserialized).to be_an_instance_of(SimpleJob)
|
24
|
+
expect(deserialized.instance_variable_get(:@check)).to eq(12)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'deserializes string tag' do
|
28
|
+
deserialized = YAML.load_dj("--- !ruby/object:RenamedString\ncheck: 12\n")
|
29
|
+
|
30
|
+
expect(deserialized).to be_an_instance_of(SimpleJob)
|
31
|
+
expect(deserialized.instance_variable_get(:@check)).to eq(12)
|
32
|
+
end
|
33
|
+
end
|
12
34
|
end
|
data/spec/worker_spec.rb
CHANGED
@@ -24,15 +24,23 @@ describe Delayed::Worker do
|
|
24
24
|
describe 'job_say' do
|
25
25
|
before do
|
26
26
|
@worker = Delayed::Worker.new
|
27
|
-
@job = double('job', :id => 123, :name => 'ExampleJob')
|
27
|
+
@job = double('job', :id => 123, :name => 'ExampleJob', :queue => nil)
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'logs with job name and id' do
|
31
|
+
expect(@job).to receive(:queue)
|
31
32
|
expect(@worker).to receive(:say).
|
32
33
|
with('Job ExampleJob (id=123) message', Delayed::Worker.default_log_level)
|
33
34
|
@worker.job_say(@job, 'message')
|
34
35
|
end
|
35
36
|
|
37
|
+
it 'logs with job name, queue and id' do
|
38
|
+
expect(@job).to receive(:queue).and_return('test')
|
39
|
+
expect(@worker).to receive(:say).
|
40
|
+
with('Job ExampleJob (id=123) (queue=test) message', Delayed::Worker.default_log_level)
|
41
|
+
@worker.job_say(@job, 'message')
|
42
|
+
end
|
43
|
+
|
36
44
|
it 'has a configurable default log level' do
|
37
45
|
Delayed::Worker.default_log_level = 'error'
|
38
46
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delayed_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.
|
4
|
+
version: 4.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Keepers
|
@@ -15,7 +15,7 @@ authors:
|
|
15
15
|
autorequire:
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
|
-
date:
|
18
|
+
date: 2020-12-09 00:00:00.000000000 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: activesupport
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
version: '3.0'
|
27
27
|
- - "<"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
29
|
+
version: '6.2'
|
30
30
|
type: :runtime
|
31
31
|
prerelease: false
|
32
32
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -36,7 +36,7 @@ dependencies:
|
|
36
36
|
version: '3.0'
|
37
37
|
- - "<"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '
|
39
|
+
version: '6.2'
|
40
40
|
description: Delayed_job (or DJ) encapsulates the common pattern of asynchronously
|
41
41
|
executing longer tasks in the background. It is a direct extraction from Shopify
|
42
42
|
where the job table is responsible for a multitude of core tasks.
|
@@ -102,7 +102,10 @@ files:
|
|
102
102
|
homepage: http://github.com/collectiveidea/delayed_job
|
103
103
|
licenses:
|
104
104
|
- MIT
|
105
|
-
metadata:
|
105
|
+
metadata:
|
106
|
+
changelog_uri: https://github.com/collectiveidea/delayed_job/blob/master/CHANGELOG.md
|
107
|
+
bug_tracker_uri: https://github.com/collectiveidea/delayed_job/issues
|
108
|
+
source_code_uri: https://github.com/collectiveidea/delayed_job
|
106
109
|
post_install_message:
|
107
110
|
rdoc_options: []
|
108
111
|
require_paths:
|
@@ -118,27 +121,26 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
121
|
- !ruby/object:Gem::Version
|
119
122
|
version: '0'
|
120
123
|
requirements: []
|
121
|
-
|
122
|
-
rubygems_version: 2.5.1
|
124
|
+
rubygems_version: 3.0.3
|
123
125
|
signing_key:
|
124
126
|
specification_version: 4
|
125
127
|
summary: Database-backed asynchronous priority queue system -- Extracted from Shopify
|
126
128
|
test_files:
|
129
|
+
- spec/sample_jobs.rb
|
130
|
+
- spec/lifecycle_spec.rb
|
131
|
+
- spec/performable_method_spec.rb
|
132
|
+
- spec/helper.rb
|
133
|
+
- spec/psych_ext_spec.rb
|
134
|
+
- spec/worker_spec.rb
|
135
|
+
- spec/autoloaded/struct.rb
|
127
136
|
- spec/autoloaded/clazz.rb
|
128
137
|
- spec/autoloaded/instance_clazz.rb
|
129
138
|
- spec/autoloaded/instance_struct.rb
|
130
|
-
- spec/
|
131
|
-
- spec/
|
139
|
+
- spec/test_backend_spec.rb
|
140
|
+
- spec/delayed/serialization/test.rb
|
132
141
|
- spec/delayed/backend/test.rb
|
133
142
|
- spec/delayed/command_spec.rb
|
134
|
-
- spec/delayed/serialization/test.rb
|
135
|
-
- spec/helper.rb
|
136
|
-
- spec/lifecycle_spec.rb
|
137
143
|
- spec/message_sending_spec.rb
|
138
144
|
- spec/performable_mailer_spec.rb
|
139
|
-
- spec/performable_method_spec.rb
|
140
|
-
- spec/psych_ext_spec.rb
|
141
|
-
- spec/sample_jobs.rb
|
142
|
-
- spec/test_backend_spec.rb
|
143
|
-
- spec/worker_spec.rb
|
144
145
|
- spec/yaml_ext_spec.rb
|
146
|
+
- spec/daemons.rb
|