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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4f13f44eb18f5903178447ab50ddd453895632b3
4
- data.tar.gz: 20c22a692ca3d8084a85fdb3e401f209d822eb3b
2
+ SHA256:
3
+ metadata.gz: 2c2e880a669ae56ceb7d75aa435f7a24540f3ff1669d5f0513eb82d7418cbcb5
4
+ data.tar.gz: aa5972d6556772c30eae6bff54bfa6fe02216d532af37d780f4da58c3beff702
5
5
  SHA512:
6
- metadata.gz: a2d9edf1e02e8fd824a5016a7761e049b0b3ae90509231d021858475dbfa7fe5695cf3a150b4564fe998e0d6fa11e39bde9017c0022ae899452a46f52d192c58
7
- data.tar.gz: a0a6875d0e951fbd0a3f442e2b699605bb36074b4c38ececaec501b721717ea64800fa191ed1ebae1b528ba7e8f7d8caee1c53115dc741870e7dc034ed916211
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.2).](https://github.com/collectiveidea/delayed_job/tree/v4.1.2)**
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.png)][gem]
9
- [![Build Status](https://travis-ci.org/collectiveidea/delayed_job.png?branch=master)][travis]
10
- [![Dependency Status](https://gemnasium.com/collectiveidea/delayed_job.png?travis)][gemnasium]
11
- [![Code Climate](https://codeclimate.com/github/collectiveidea/delayed_job.png)][codeclimate]
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+. See the [2.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, see [below](#rails-42)
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
- Rails 4.2
74
- =========
75
- Set the queue_adapter in config/application.rb
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 3 Mailers
175
- ===============
176
- Due to how mailers are implemented in Rails 3, we had to do a little work around to get delayed_job to work.
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
- # with delayed_job running at a specific time
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
- Remove the `.deliver` method to make it work. It's not ideal, but it's the best
190
- we could do for now.
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', '< 5.1']
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.2'
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
@@ -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 == 0 ? method.call : method.call(self, *args)
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
- update_attributes(:failed_at => self.class.db_time_now)
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.update_attributes :text => 'goodbye'
526
+ story.text = 'goodbye'
527
+ story.save!
521
528
  expect(job.reload.payload_object.object.text).to eq('goodbye')
522
529
  end
523
530
 
@@ -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}"
@@ -8,5 +8,5 @@ module Delayed
8
8
  end
9
9
  end
10
10
 
11
- class FatalBackendError < Exception; end
11
+ class FatalBackendError < RuntimeError; end
12
12
  end
@@ -1,5 +1,5 @@
1
1
  module Delayed
2
- class InvalidCallback < Exception; end
2
+ class InvalidCallback < RuntimeError; end
3
3
 
4
4
  class Lifecycle
5
5
  EVENTS = {
@@ -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
- module ClassMethods
31
- def handle_asynchronously(method, opts = {}) # rubocop:disable PerceivedComplexity
32
- aliased_method = method.to_s.sub(/([?!=])$/, '')
33
- punctuation = $1 # rubocop:disable PerlBackrefs
34
- with_method = "#{aliased_method}_with_delay#{punctuation}"
35
- without_method = "#{aliased_method}_without_delay#{punctuation}"
36
- define_method(with_method) do |*args|
37
- curr_opts = opts.clone
38
- curr_opts.each_key do |key|
39
- next unless (val = curr_opts[key]).is_a?(Proc)
40
- curr_opts[key] = if val.arity == 1
41
- val.call(self)
42
- else
43
- val.call
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
- alias_method without_method, method
50
- alias_method method, with_method
52
+ alias_method without_method, method
53
+ alias_method method, with_method
51
54
 
52
- if public_method_defined?(without_method)
53
- public method
54
- elsif protected_method_defined?(without_method)
55
- protected method
56
- elsif private_method_defined?(without_method)
57
- private method
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)
@@ -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
- return revive(Psych.load_tags[object.tag], object) if Psych.load_tags[object.tag]
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 defined?(ActiveRecord::Base) && result.is_a?(ActiveRecord::Base)
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
@@ -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)
@@ -1,7 +1,7 @@
1
1
  if defined?(ActiveRecord)
2
2
  module ActiveRecord
3
3
  class Base
4
- yaml_as 'tag:ruby.yaml.org,2002:ActiveRecord'
4
+ yaml_tag 'tag:ruby.yaml.org,2002:ActiveRecord'
5
5
 
6
6
  def self.yaml_new(klass, _tag, val)
7
7
  klass.unscoped.find(val['attributes'][klass.primary_key])
@@ -1,5 +1,5 @@
1
1
  class Module
2
- yaml_as 'tag:ruby.yaml.org,2002:module'
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
- yaml_as 'tag:ruby.yaml.org,2002:class'
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
 
@@ -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, "REMOVED permanently because of #{job.attempts} consecutive failures", 'error'
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
- ActionDispatch::Reloader.cleanup!
324
- ActionDispatch::Reloader.prepare!
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::MessageSending::ClassMethods)
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", 0755
9
+ chmod "#{Delayed::Compatibility.executable_prefix}/delayed_job", 0o755
10
10
  end
11
11
  end
@@ -1,7 +1,6 @@
1
1
  # Make sure this file does not get required manually
2
2
  module Autoloaded
3
3
  class Clazz
4
- def perform
5
- end
4
+ def perform; end
6
5
  end
7
6
  end
@@ -1,6 +1,5 @@
1
1
  module Autoloaded
2
2
  class InstanceClazz
3
- def perform
4
- end
3
+ def perform; end
5
4
  end
6
5
  end
@@ -1,7 +1,6 @@
1
1
  module Autoloaded
2
2
  InstanceStruct = ::Struct.new(nil)
3
3
  class InstanceStruct
4
- def perform
5
- end
4
+ def perform; end
6
5
  end
7
6
  end
@@ -2,7 +2,6 @@
2
2
  module Autoloaded
3
3
  Struct = ::Struct.new(nil)
4
4
  class Struct
5
- def perform
6
- end
5
+ def perform; end
7
6
  end
8
7
  end
@@ -87,11 +87,6 @@ module Delayed
87
87
  Time.current
88
88
  end
89
89
 
90
- def update_attributes(attrs = {})
91
- attrs.each { |k, v| send(:"#{k}=", v) }
92
- save
93
- end
94
-
95
90
  def destroy
96
91
  self.class.all.delete(self)
97
92
  end
data/spec/helper.rb CHANGED
@@ -1,20 +1,25 @@
1
1
  require 'simplecov'
2
- require 'coveralls'
2
+ require 'simplecov-lcov'
3
3
 
4
- SimpleCov.formatters = [SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter]
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 change { Delayed::Job.count }
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 change { Delayed::Job.count }
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 change { Delayed::Job.count }
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
@@ -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.load("--- !ruby/object:BigDecimal 18:0.1337E2\n...\n")
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.2
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: 2016-05-16 00:00:00.000000000 Z
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: '5.1'
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: '5.1'
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
- rubyforge_project:
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/autoloaded/struct.rb
131
- - spec/daemons.rb
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