activejob 6.1.4 → 7.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -132
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +3 -3
  5. data/lib/active_job/arguments.rb +10 -15
  6. data/lib/active_job/base.rb +2 -2
  7. data/lib/active_job/callbacks.rb +3 -28
  8. data/lib/active_job/configured_job.rb +5 -7
  9. data/lib/active_job/core.rb +21 -1
  10. data/lib/active_job/enqueuing.rb +23 -13
  11. data/lib/active_job/exceptions.rb +4 -2
  12. data/lib/active_job/execution.rb +13 -8
  13. data/lib/active_job/gem_version.rb +4 -4
  14. data/lib/active_job/instrumentation.rb +9 -5
  15. data/lib/active_job/log_subscriber.rb +1 -1
  16. data/lib/active_job/logging.rb +8 -5
  17. data/lib/active_job/queue_adapter.rb +1 -1
  18. data/lib/active_job/queue_adapters/async_adapter.rb +6 -6
  19. data/lib/active_job/queue_adapters/backburner_adapter.rb +3 -3
  20. data/lib/active_job/queue_adapters/delayed_job_adapter.rb +14 -4
  21. data/lib/active_job/queue_adapters/inline_adapter.rb +2 -2
  22. data/lib/active_job/queue_adapters/que_adapter.rb +3 -3
  23. data/lib/active_job/queue_adapters/queue_classic_adapter.rb +3 -3
  24. data/lib/active_job/queue_adapters/resque_adapter.rb +3 -3
  25. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +3 -3
  26. data/lib/active_job/queue_adapters/sneakers_adapter.rb +3 -3
  27. data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +3 -3
  28. data/lib/active_job/queue_adapters/test_adapter.rb +3 -2
  29. data/lib/active_job/queue_name.rb +1 -1
  30. data/lib/active_job/railtie.rb +22 -1
  31. data/lib/active_job/serializers/module_serializer.rb +1 -0
  32. data/lib/active_job/serializers/range_serializer.rb +23 -0
  33. data/lib/active_job/serializers.rb +3 -1
  34. data/lib/active_job/test_helper.rb +37 -13
  35. data/lib/active_job/timezones.rb +1 -1
  36. data/lib/active_job/translation.rb +1 -1
  37. data/lib/active_job.rb +2 -1
  38. metadata +13 -11
@@ -4,22 +4,25 @@ require "active_support/tagged_logging"
4
4
  require "active_support/logger"
5
5
 
6
6
  module ActiveJob
7
- module Logging #:nodoc:
7
+ module Logging # :nodoc:
8
8
  extend ActiveSupport::Concern
9
9
 
10
10
  included do
11
11
  cattr_accessor :logger, default: ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT))
12
12
  class_attribute :log_arguments, instance_accessor: false, default: true
13
13
 
14
- around_enqueue { |_, block| tag_logger(&block) }
15
- around_perform { |job, block| tag_logger(job.class.name, job.job_id, &block) }
14
+ around_enqueue(prepend: true) { |_, block| tag_logger(&block) }
15
+ end
16
+
17
+ def perform_now
18
+ tag_logger(self.class.name, self.job_id) { super }
16
19
  end
17
20
 
18
21
  private
19
- def tag_logger(*tags)
22
+ def tag_logger(*tags, &block)
20
23
  if logger.respond_to?(:tagged)
21
24
  tags.unshift "ActiveJob" unless logger_tagged_by_active_job?
22
- logger.tagged(*tags) { yield }
25
+ logger.tagged(*tags, &block)
23
26
  else
24
27
  yield
25
28
  end
@@ -5,7 +5,7 @@ require "active_support/core_ext/string/inflections"
5
5
  module ActiveJob
6
6
  # The <tt>ActiveJob::QueueAdapter</tt> module is used to load the
7
7
  # correct adapter. The default queue adapter is the +:async+ queue.
8
- module QueueAdapter #:nodoc:
8
+ module QueueAdapter # :nodoc:
9
9
  extend ActiveSupport::Concern
10
10
 
11
11
  included do
@@ -36,23 +36,23 @@ module ActiveJob
36
36
  @scheduler = Scheduler.new(**executor_options)
37
37
  end
38
38
 
39
- def enqueue(job) #:nodoc:
39
+ def enqueue(job) # :nodoc:
40
40
  @scheduler.enqueue JobWrapper.new(job), queue_name: job.queue_name
41
41
  end
42
42
 
43
- def enqueue_at(job, timestamp) #:nodoc:
43
+ def enqueue_at(job, timestamp) # :nodoc:
44
44
  @scheduler.enqueue_at JobWrapper.new(job), timestamp, queue_name: job.queue_name
45
45
  end
46
46
 
47
47
  # Gracefully stop processing jobs. Finishes in-progress work and handles
48
48
  # any new jobs following the executor's fallback policy (`caller_runs`).
49
49
  # Waits for termination by default. Pass `wait: false` to continue.
50
- def shutdown(wait: true) #:nodoc:
50
+ def shutdown(wait: true) # :nodoc:
51
51
  @scheduler.shutdown wait: wait
52
52
  end
53
53
 
54
54
  # Used for our test suite.
55
- def immediate=(immediate) #:nodoc:
55
+ def immediate=(immediate) # :nodoc:
56
56
  @scheduler.immediate = immediate
57
57
  end
58
58
 
@@ -60,7 +60,7 @@ module ActiveJob
60
60
  # performing them in-process, but we do so anyway for parity with other
61
61
  # adapters and deployment environments. Otherwise, serialization bugs
62
62
  # may creep in undetected.
63
- class JobWrapper #:nodoc:
63
+ class JobWrapper # :nodoc:
64
64
  def initialize(job)
65
65
  job.provider_job_id = SecureRandom.uuid
66
66
  @job_data = job.serialize
@@ -71,7 +71,7 @@ module ActiveJob
71
71
  end
72
72
  end
73
73
 
74
- class Scheduler #:nodoc:
74
+ class Scheduler # :nodoc:
75
75
  DEFAULT_EXECUTOR_OPTIONS = {
76
76
  min_threads: 0,
77
77
  max_threads: Concurrent.processor_count,
@@ -15,16 +15,16 @@ module ActiveJob
15
15
  #
16
16
  # Rails.application.config.active_job.queue_adapter = :backburner
17
17
  class BackburnerAdapter
18
- def enqueue(job) #:nodoc:
18
+ def enqueue(job) # :nodoc:
19
19
  Backburner::Worker.enqueue(JobWrapper, [job.serialize], queue: job.queue_name, pri: job.priority)
20
20
  end
21
21
 
22
- def enqueue_at(job, timestamp) #:nodoc:
22
+ def enqueue_at(job, timestamp) # :nodoc:
23
23
  delay = timestamp - Time.current.to_f
24
24
  Backburner::Worker.enqueue(JobWrapper, [job.serialize], queue: job.queue_name, pri: job.priority, delay: delay)
25
25
  end
26
26
 
27
- class JobWrapper #:nodoc:
27
+ class JobWrapper # :nodoc:
28
28
  class << self
29
29
  def perform(job_data)
30
30
  Base.execute job_data
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "delayed_job"
4
+ require "active_support/core_ext/string/inflections"
4
5
 
5
6
  module ActiveJob
6
7
  module QueueAdapters
@@ -15,19 +16,19 @@ module ActiveJob
15
16
  #
16
17
  # Rails.application.config.active_job.queue_adapter = :delayed_job
17
18
  class DelayedJobAdapter
18
- def enqueue(job) #:nodoc:
19
+ def enqueue(job) # :nodoc:
19
20
  delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, priority: job.priority)
20
21
  job.provider_job_id = delayed_job.id
21
22
  delayed_job
22
23
  end
23
24
 
24
- def enqueue_at(job, timestamp) #:nodoc:
25
+ def enqueue_at(job, timestamp) # :nodoc:
25
26
  delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, priority: job.priority, run_at: Time.at(timestamp))
26
27
  job.provider_job_id = delayed_job.id
27
28
  delayed_job
28
29
  end
29
30
 
30
- class JobWrapper #:nodoc:
31
+ class JobWrapper # :nodoc:
31
32
  attr_accessor :job_data
32
33
 
33
34
  def initialize(job_data)
@@ -35,12 +36,21 @@ module ActiveJob
35
36
  end
36
37
 
37
38
  def display_name
38
- "#{job_data['job_class']} [#{job_data['job_id']}] from DelayedJob(#{job_data['queue_name']}) with arguments: #{job_data['arguments']}"
39
+ base_name = "#{job_data["job_class"]} [#{job_data["job_id"]}] from DelayedJob(#{job_data["queue_name"]})"
40
+
41
+ return base_name unless log_arguments?
42
+
43
+ "#{base_name} with arguments: #{job_data["arguments"]}"
39
44
  end
40
45
 
41
46
  def perform
42
47
  Base.execute(job_data)
43
48
  end
49
+
50
+ private
51
+ def log_arguments?
52
+ job_data["job_class"].constantize.log_arguments?
53
+ end
44
54
  end
45
55
  end
46
56
  end
@@ -11,11 +11,11 @@ module ActiveJob
11
11
  #
12
12
  # Rails.application.config.active_job.queue_adapter = :inline
13
13
  class InlineAdapter
14
- def enqueue(job) #:nodoc:
14
+ def enqueue(job) # :nodoc:
15
15
  Base.execute(job.serialize)
16
16
  end
17
17
 
18
- def enqueue_at(*) #:nodoc:
18
+ def enqueue_at(*) # :nodoc:
19
19
  raise NotImplementedError, "Use a queueing backend to enqueue jobs in the future. Read more at https://guides.rubyonrails.org/active_job_basics.html"
20
20
  end
21
21
  end
@@ -17,19 +17,19 @@ module ActiveJob
17
17
  #
18
18
  # Rails.application.config.active_job.queue_adapter = :que
19
19
  class QueAdapter
20
- def enqueue(job) #:nodoc:
20
+ def enqueue(job) # :nodoc:
21
21
  que_job = JobWrapper.enqueue job.serialize, priority: job.priority, queue: job.queue_name
22
22
  job.provider_job_id = que_job.attrs["job_id"]
23
23
  que_job
24
24
  end
25
25
 
26
- def enqueue_at(job, timestamp) #:nodoc:
26
+ def enqueue_at(job, timestamp) # :nodoc:
27
27
  que_job = JobWrapper.enqueue job.serialize, priority: job.priority, queue: job.queue_name, run_at: Time.at(timestamp)
28
28
  job.provider_job_id = que_job.attrs["job_id"]
29
29
  que_job
30
30
  end
31
31
 
32
- class JobWrapper < Que::Job #:nodoc:
32
+ class JobWrapper < Que::Job # :nodoc:
33
33
  def run(job_data)
34
34
  Base.execute job_data
35
35
  end
@@ -19,13 +19,13 @@ module ActiveJob
19
19
  #
20
20
  # Rails.application.config.active_job.queue_adapter = :queue_classic
21
21
  class QueueClassicAdapter
22
- def enqueue(job) #:nodoc:
22
+ def enqueue(job) # :nodoc:
23
23
  qc_job = build_queue(job.queue_name).enqueue("#{JobWrapper.name}.perform", job.serialize)
24
24
  job.provider_job_id = qc_job["id"] if qc_job.is_a?(Hash)
25
25
  qc_job
26
26
  end
27
27
 
28
- def enqueue_at(job, timestamp) #:nodoc:
28
+ def enqueue_at(job, timestamp) # :nodoc:
29
29
  queue = build_queue(job.queue_name)
30
30
  unless queue.respond_to?(:enqueue_at)
31
31
  raise NotImplementedError, "To be able to schedule jobs with queue_classic " \
@@ -46,7 +46,7 @@ module ActiveJob
46
46
  QC::Queue.new(queue_name)
47
47
  end
48
48
 
49
- class JobWrapper #:nodoc:
49
+ class JobWrapper # :nodoc:
50
50
  class << self
51
51
  def perform(job_data)
52
52
  Base.execute job_data
@@ -28,12 +28,12 @@ module ActiveJob
28
28
  #
29
29
  # Rails.application.config.active_job.queue_adapter = :resque
30
30
  class ResqueAdapter
31
- def enqueue(job) #:nodoc:
31
+ def enqueue(job) # :nodoc:
32
32
  JobWrapper.instance_variable_set(:@queue, job.queue_name)
33
33
  Resque.enqueue_to job.queue_name, JobWrapper, job.serialize
34
34
  end
35
35
 
36
- def enqueue_at(job, timestamp) #:nodoc:
36
+ def enqueue_at(job, timestamp) # :nodoc:
37
37
  unless Resque.respond_to?(:enqueue_at_with_queue)
38
38
  raise NotImplementedError, "To be able to schedule jobs with Resque you need the " \
39
39
  "resque-scheduler gem. Please add it to your Gemfile and run bundle install"
@@ -41,7 +41,7 @@ module ActiveJob
41
41
  Resque.enqueue_at_with_queue job.queue_name, timestamp, JobWrapper, job.serialize
42
42
  end
43
43
 
44
- class JobWrapper #:nodoc:
44
+ class JobWrapper # :nodoc:
45
45
  class << self
46
46
  def perform(job_data)
47
47
  Base.execute job_data
@@ -17,7 +17,7 @@ module ActiveJob
17
17
  #
18
18
  # Rails.application.config.active_job.queue_adapter = :sidekiq
19
19
  class SidekiqAdapter
20
- def enqueue(job) #:nodoc:
20
+ def enqueue(job) # :nodoc:
21
21
  # Sidekiq::Client does not support symbols as keys
22
22
  job.provider_job_id = Sidekiq::Client.push \
23
23
  "class" => JobWrapper,
@@ -26,7 +26,7 @@ module ActiveJob
26
26
  "args" => [ job.serialize ]
27
27
  end
28
28
 
29
- def enqueue_at(job, timestamp) #:nodoc:
29
+ def enqueue_at(job, timestamp) # :nodoc:
30
30
  job.provider_job_id = Sidekiq::Client.push \
31
31
  "class" => JobWrapper,
32
32
  "wrapped" => job.class,
@@ -35,7 +35,7 @@ module ActiveJob
35
35
  "at" => timestamp
36
36
  end
37
37
 
38
- class JobWrapper #:nodoc:
38
+ class JobWrapper # :nodoc:
39
39
  include Sidekiq::Worker
40
40
 
41
41
  def perform(job_data)
@@ -22,18 +22,18 @@ module ActiveJob
22
22
  @monitor = Monitor.new
23
23
  end
24
24
 
25
- def enqueue(job) #:nodoc:
25
+ def enqueue(job) # :nodoc:
26
26
  @monitor.synchronize do
27
27
  JobWrapper.from_queue job.queue_name
28
28
  JobWrapper.enqueue ActiveSupport::JSON.encode(job.serialize)
29
29
  end
30
30
  end
31
31
 
32
- def enqueue_at(job, timestamp) #:nodoc:
32
+ def enqueue_at(job, timestamp) # :nodoc:
33
33
  raise NotImplementedError, "This queueing backend does not support scheduling jobs. To see what features are supported go to http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html"
34
34
  end
35
35
 
36
- class JobWrapper #:nodoc:
36
+ class JobWrapper # :nodoc:
37
37
  include Sneakers::Worker
38
38
  from_queue "default"
39
39
 
@@ -18,7 +18,7 @@ module ActiveJob
18
18
  #
19
19
  # Rails.application.config.active_job.queue_adapter = :sucker_punch
20
20
  class SuckerPunchAdapter
21
- def enqueue(job) #:nodoc:
21
+ def enqueue(job) # :nodoc:
22
22
  if JobWrapper.respond_to?(:perform_async)
23
23
  # sucker_punch 2.0 API
24
24
  JobWrapper.perform_async job.serialize
@@ -28,7 +28,7 @@ module ActiveJob
28
28
  end
29
29
  end
30
30
 
31
- def enqueue_at(job, timestamp) #:nodoc:
31
+ def enqueue_at(job, timestamp) # :nodoc:
32
32
  if JobWrapper.respond_to?(:perform_in)
33
33
  delay = timestamp - Time.current.to_f
34
34
  JobWrapper.perform_in delay, job.serialize
@@ -37,7 +37,7 @@ module ActiveJob
37
37
  end
38
38
  end
39
39
 
40
- class JobWrapper #:nodoc:
40
+ class JobWrapper # :nodoc:
41
41
  include SuckerPunch::Job
42
42
 
43
43
  def perform(job_data)
@@ -25,12 +25,12 @@ module ActiveJob
25
25
  @performed_jobs ||= []
26
26
  end
27
27
 
28
- def enqueue(job) #:nodoc:
28
+ def enqueue(job) # :nodoc:
29
29
  job_data = job_to_hash(job)
30
30
  perform_or_enqueue(perform_enqueued_jobs && !filtered?(job), job, job_data)
31
31
  end
32
32
 
33
- def enqueue_at(job, timestamp) #:nodoc:
33
+ def enqueue_at(job, timestamp) # :nodoc:
34
34
  job_data = job_to_hash(job, at: timestamp)
35
35
  perform_or_enqueue(perform_enqueued_at_jobs && !filtered?(job), job, job_data)
36
36
  end
@@ -41,6 +41,7 @@ module ActiveJob
41
41
  job_data[:job] = job.class
42
42
  job_data[:args] = job_data.fetch("arguments")
43
43
  job_data[:queue] = job_data.fetch("queue_name")
44
+ job_data[:priority] = job_data.fetch("priority")
44
45
  end.merge(extras)
45
46
  end
46
47
 
@@ -45,7 +45,7 @@ module ActiveJob
45
45
  end
46
46
  end
47
47
 
48
- def queue_name_from_part(part_name) #:nodoc:
48
+ def queue_name_from_part(part_name) # :nodoc:
49
49
  queue_name = part_name || default_queue_name
50
50
  name_parts = [queue_name_prefix.presence, queue_name]
51
51
  -name_parts.compact.join(queue_name_delimiter)
@@ -8,6 +8,7 @@ module ActiveJob
8
8
  class Railtie < Rails::Railtie # :nodoc:
9
9
  config.active_job = ActiveSupport::OrderedOptions.new
10
10
  config.active_job.custom_serializers = []
11
+ config.active_job.log_query_tags_around_perform = true
11
12
 
12
13
  initializer "active_job.logger" do
13
14
  ActiveSupport.on_load(:active_job) { self.logger = ::Rails.logger }
@@ -15,7 +16,7 @@ module ActiveJob
15
16
 
16
17
  initializer "active_job.custom_serializers" do |app|
17
18
  config.after_initialize do
18
- custom_serializers = app.config.active_job.delete(:custom_serializers)
19
+ custom_serializers = app.config.active_job.custom_serializers
19
20
  ActiveJob::Serializers.add_serializers custom_serializers
20
21
  end
21
22
  end
@@ -25,6 +26,12 @@ module ActiveJob
25
26
  options.queue_adapter ||= :async
26
27
 
27
28
  ActiveSupport.on_load(:active_job) do
29
+ # Configs used in other initializers
30
+ options = options.except(
31
+ :log_query_tags_around_perform,
32
+ :custom_serializers
33
+ )
34
+
28
35
  options.each do |k, v|
29
36
  k = "#{k}="
30
37
  send(k, v) if respond_to? k
@@ -49,5 +56,19 @@ module ActiveJob
49
56
  end
50
57
  end
51
58
  end
59
+
60
+ initializer "active_job.query_log_tags" do |app|
61
+ query_logs_tags_enabled = app.config.respond_to?(:active_record) &&
62
+ app.config.active_record.query_log_tags_enabled &&
63
+ app.config.active_job.log_query_tags_around_perform
64
+
65
+ if query_logs_tags_enabled
66
+ app.config.active_record.query_log_tags << :job
67
+
68
+ ActiveSupport.on_load(:active_record) do
69
+ ActiveRecord::QueryLogs.taggings[:job] = ->(context) { context[:job].class.name if context[:job] }
70
+ end
71
+ end
72
+ end
52
73
  end
53
74
  end
@@ -4,6 +4,7 @@ module ActiveJob
4
4
  module Serializers
5
5
  class ModuleSerializer < ObjectSerializer # :nodoc:
6
6
  def serialize(constant)
7
+ raise SerializationError, "Serializing an anonymous class is not supported" unless constant.name
7
8
  super("value" => constant.name)
8
9
  end
9
10
 
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module Serializers
5
+ class RangeSerializer < ObjectSerializer
6
+ KEYS = %w[begin end exclude_end].freeze
7
+
8
+ def serialize(range)
9
+ args = Arguments.serialize([range.begin, range.end, range.exclude_end?])
10
+ super(KEYS.zip(args).to_h)
11
+ end
12
+
13
+ def deserialize(hash)
14
+ klass.new(*Arguments.deserialize(hash.values_at(*KEYS)))
15
+ end
16
+
17
+ private
18
+ def klass
19
+ ::Range
20
+ end
21
+ end
22
+ end
23
+ end
@@ -17,6 +17,7 @@ module ActiveJob
17
17
  autoload :TimeWithZoneSerializer
18
18
  autoload :TimeSerializer
19
19
  autoload :ModuleSerializer
20
+ autoload :RangeSerializer
20
21
 
21
22
  mattr_accessor :_additional_serializers
22
23
  self._additional_serializers = Set.new
@@ -61,6 +62,7 @@ module ActiveJob
61
62
  DateSerializer,
62
63
  TimeWithZoneSerializer,
63
64
  TimeSerializer,
64
- ModuleSerializer
65
+ ModuleSerializer,
66
+ RangeSerializer
65
67
  end
66
68
  end
@@ -109,7 +109,7 @@ module ActiveJob
109
109
  # end
110
110
  # end
111
111
  #
112
- # +:only+ and +:except+ options accepts Class, Array of Class or Proc. When passed a Proc,
112
+ # +:only+ and +:except+ options accept Class, Array of Class or Proc. When passed a Proc,
113
113
  # a hash containing the job's class and it's argument are passed as argument.
114
114
  #
115
115
  # Asserts the number of times a job is enqueued to a specific queue by passing +:queue+ option.
@@ -124,7 +124,7 @@ module ActiveJob
124
124
  if block_given?
125
125
  original_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
126
126
 
127
- assert_nothing_raised(&block)
127
+ _assert_nothing_raised_or_warn("assert_enqueued_jobs", &block)
128
128
 
129
129
  new_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
130
130
 
@@ -168,7 +168,7 @@ module ActiveJob
168
168
  # end
169
169
  # end
170
170
  #
171
- # +:only+ and +:except+ options accepts Class, Array of Class or Proc. When passed a Proc,
171
+ # +:only+ and +:except+ options accept Class, Array of Class or Proc. When passed a Proc,
172
172
  # a hash containing the job's class and it's argument are passed as argument.
173
173
  #
174
174
  # Asserts that no jobs are enqueued to a specific queue by passing +:queue+ option
@@ -325,7 +325,7 @@ module ActiveJob
325
325
  # end
326
326
  # end
327
327
  #
328
- # +:only+ and +:except+ options accepts Class, Array of Class or Proc. When passed a Proc,
328
+ # +:only+ and +:except+ options accept Class, Array of Class or Proc. When passed a Proc,
329
329
  # an instance of the job will be passed as argument.
330
330
  #
331
331
  # If the +:queue+ option is specified,
@@ -389,15 +389,15 @@ module ActiveJob
389
389
  # MyJob.set(wait_until: Date.tomorrow.noon).perform_later
390
390
  # end
391
391
  # end
392
- def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil, &block)
393
- expected = { job: job, args: args, at: at, queue: queue }.compact
392
+ def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block)
393
+ expected = { job: job, args: args, at: at, queue: queue, priority: priority }.compact
394
394
  expected_args = prepare_args_for_assertion(expected)
395
395
  potential_matches = []
396
396
 
397
397
  if block_given?
398
398
  original_enqueued_jobs = enqueued_jobs.dup
399
399
 
400
- assert_nothing_raised(&block)
400
+ _assert_nothing_raised_or_warn("assert_enqueued_with", &block)
401
401
 
402
402
  jobs = enqueued_jobs - original_enqueued_jobs
403
403
  else
@@ -417,8 +417,20 @@ module ActiveJob
417
417
  end
418
418
  end
419
419
 
420
+ matching_class = potential_matches.select do |enqueued_job|
421
+ enqueued_job["job_class"] == job.to_s
422
+ end
423
+
420
424
  message = +"No enqueued job found with #{expected}"
421
- message << "\n\nPotential matches: #{potential_matches.join("\n")}" if potential_matches.present?
425
+ if potential_matches.empty?
426
+ message << "\n\nNo jobs were enqueued"
427
+ elsif matching_class.empty?
428
+ message << "\n\nNo jobs of class #{expected[:job]} were enqueued, job classes enqueued: "
429
+ message << potential_matches.map { |job| job["job_class"] }.join(", ")
430
+ else
431
+ message << "\n\nPotential matches: #{matching_class.join("\n")}"
432
+ end
433
+
422
434
  assert matching_job, message
423
435
  instantiate_job(matching_job)
424
436
  end
@@ -479,8 +491,8 @@ module ActiveJob
479
491
  # MyJob.set(wait_until: Date.tomorrow.noon).perform_later
480
492
  # end
481
493
  # end
482
- def assert_performed_with(job: nil, args: nil, at: nil, queue: nil, &block)
483
- expected = { job: job, args: args, at: at, queue: queue }.compact
494
+ def assert_performed_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block)
495
+ expected = { job: job, args: args, at: at, queue: queue, priority: priority }.compact
484
496
  expected_args = prepare_args_for_assertion(expected)
485
497
  potential_matches = []
486
498
 
@@ -507,8 +519,20 @@ module ActiveJob
507
519
  end
508
520
  end
509
521
 
522
+ matching_class = potential_matches.select do |enqueued_job|
523
+ enqueued_job["job_class"] == job.to_s
524
+ end
525
+
510
526
  message = +"No performed job found with #{expected}"
511
- message << "\n\nPotential matches: #{potential_matches.join("\n")}" if potential_matches.present?
527
+ if potential_matches.empty?
528
+ message << "\n\nNo jobs were performed"
529
+ elsif matching_class.empty?
530
+ message << "\n\nNo jobs of class #{expected[:job]} were performed, job classes performed: "
531
+ message << potential_matches.map { |job| job["job_class"] }.join(", ")
532
+ else
533
+ message << "\n\nPotential matches: #{matching_class.join("\n")}"
534
+ end
535
+
512
536
  assert matching_job, message
513
537
 
514
538
  instantiate_job(matching_job)
@@ -555,7 +579,7 @@ module ActiveJob
555
579
  # assert_performed_jobs 1
556
580
  # end
557
581
  #
558
- # +:only+ and +:except+ options accepts Class, Array of Class or Proc. When passed a Proc,
582
+ # +:only+ and +:except+ options accept Class, Array of Class or Proc. When passed a Proc,
559
583
  # an instance of the job will be passed as argument.
560
584
  #
561
585
  # If the +:queue+ option is specified,
@@ -591,7 +615,7 @@ module ActiveJob
591
615
  queue_adapter.queue = queue
592
616
  queue_adapter.at = at
593
617
 
594
- assert_nothing_raised(&block)
618
+ _assert_nothing_raised_or_warn("perform_enqueued_jobs", &block)
595
619
  ensure
596
620
  queue_adapter.perform_enqueued_jobs = old_perform_enqueued_jobs
597
621
  queue_adapter.perform_enqueued_at_jobs = old_perform_enqueued_at_jobs
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveJob
4
- module Timezones #:nodoc:
4
+ module Timezones # :nodoc:
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveJob
4
- module Translation #:nodoc:
4
+ module Translation # :nodoc:
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
data/lib/active_job.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2014-2020 David Heinemeier Hansson
4
+ # Copyright (c) 2014-2021 David Heinemeier Hansson
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining
7
7
  # a copy of this software and associated documentation files (the
@@ -37,4 +37,5 @@ module ActiveJob
37
37
  autoload :ConfiguredJob
38
38
  autoload :TestCase
39
39
  autoload :TestHelper
40
+ autoload :QueryTags
40
41
  end