activejob 7.0.8 → 7.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +147 -150
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +2 -2
  5. data/lib/active_job/arguments.rb +14 -25
  6. data/lib/active_job/base.rb +1 -1
  7. data/lib/active_job/callbacks.rb +1 -4
  8. data/lib/active_job/configured_job.rb +4 -0
  9. data/lib/active_job/core.rb +26 -6
  10. data/lib/active_job/deprecator.rb +7 -0
  11. data/lib/active_job/enqueuing.rb +31 -1
  12. data/lib/active_job/exceptions.rb +48 -5
  13. data/lib/active_job/execution.rb +5 -1
  14. data/lib/active_job/gem_version.rb +3 -3
  15. data/lib/active_job/instrumentation.rb +18 -10
  16. data/lib/active_job/log_subscriber.rb +80 -8
  17. data/lib/active_job/queue_adapter.rb +13 -2
  18. data/lib/active_job/queue_adapters/async_adapter.rb +2 -2
  19. data/lib/active_job/queue_adapters/backburner_adapter.rb +7 -3
  20. data/lib/active_job/queue_adapters/delayed_job_adapter.rb +1 -1
  21. data/lib/active_job/queue_adapters/inline_adapter.rb +1 -1
  22. data/lib/active_job/queue_adapters/queue_classic_adapter.rb +4 -4
  23. data/lib/active_job/queue_adapters/resque_adapter.rb +1 -1
  24. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +42 -14
  25. data/lib/active_job/queue_adapters/sneakers_adapter.rb +1 -1
  26. data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +2 -2
  27. data/lib/active_job/queue_adapters/test_adapter.rb +3 -3
  28. data/lib/active_job/queue_adapters.rb +8 -7
  29. data/lib/active_job/queue_priority.rb +18 -1
  30. data/lib/active_job/railtie.rb +25 -6
  31. data/lib/active_job/serializers/big_decimal_serializer.rb +22 -0
  32. data/lib/active_job/serializers/duration_serializer.rb +4 -2
  33. data/lib/active_job/serializers.rb +7 -3
  34. data/lib/active_job/test_helper.rb +29 -13
  35. data/lib/active_job/version.rb +1 -1
  36. data/lib/active_job.rb +26 -4
  37. data/lib/rails/generators/job/USAGE +19 -0
  38. data/lib/rails/generators/job/job_generator.rb +6 -2
  39. data/lib/rails/generators/job/templates/job.rb.tt +1 -1
  40. metadata +10 -8
  41. data/lib/active_job/queue_adapters/que_adapter.rb +0 -61
@@ -18,7 +18,24 @@ module ActiveJob
18
18
  # end
19
19
  # end
20
20
  #
21
- # Specify either an argument or a block.
21
+ # Can be given a block that will evaluate in the context of the job
22
+ # so that a dynamic priority can be applied:
23
+ #
24
+ # class PublishToFeedJob < ApplicationJob
25
+ # queue_with_priority do
26
+ # post = self.arguments.first
27
+ #
28
+ # if post.paid?
29
+ # 10
30
+ # else
31
+ # 50
32
+ # end
33
+ # end
34
+ #
35
+ # def perform(post)
36
+ # post.to_feed!
37
+ # end
38
+ # end
22
39
  def queue_with_priority(priority = nil, &block)
23
40
  if block_given?
24
41
  self.priority = block
@@ -10,6 +10,10 @@ module ActiveJob
10
10
  config.active_job.custom_serializers = []
11
11
  config.active_job.log_query_tags_around_perform = true
12
12
 
13
+ initializer "active_job.deprecator", before: :load_environment_config do |app|
14
+ app.deprecators[:active_job] = ActiveJob.deprecator
15
+ end
16
+
13
17
  initializer "active_job.logger" do
14
18
  ActiveSupport.on_load(:active_job) { self.logger = ::Rails.logger }
15
19
  end
@@ -25,6 +29,15 @@ module ActiveJob
25
29
  options = app.config.active_job
26
30
  options.queue_adapter ||= :async
27
31
 
32
+ config.after_initialize do
33
+ options.each do |k, v|
34
+ k = "#{k}="
35
+ if ActiveJob.respond_to?(k)
36
+ ActiveJob.send(k, v)
37
+ end
38
+ end
39
+ end
40
+
28
41
  ActiveSupport.on_load(:active_job) do
29
42
  # Configs used in other initializers
30
43
  options = options.except(
@@ -32,19 +45,19 @@ module ActiveJob
32
45
  :custom_serializers
33
46
  )
34
47
 
35
- options.each do |k, v|
48
+ options.each do |k, v|
36
49
  k = "#{k}="
37
- send(k, v) if respond_to? k
50
+ if ActiveJob.respond_to?(k)
51
+ ActiveJob.send(k, v)
52
+ elsif respond_to? k
53
+ send(k, v)
54
+ end
38
55
  end
39
56
  end
40
57
 
41
58
  ActiveSupport.on_load(:action_dispatch_integration_test) do
42
59
  include ActiveJob::TestHelper
43
60
  end
44
-
45
- ActiveSupport.on_load(:active_record) do
46
- self.destroy_association_async_job = ActiveRecord::DestroyAssociationAsyncJob
47
- end
48
61
  end
49
62
 
50
63
  initializer "active_job.set_reloader_hook" do |app|
@@ -70,5 +83,11 @@ module ActiveJob
70
83
  end
71
84
  end
72
85
  end
86
+
87
+ initializer "active_job.backtrace_cleaner" do
88
+ ActiveSupport.on_load(:active_job) do
89
+ LogSubscriber.backtrace_cleaner = ::Rails.backtrace_cleaner
90
+ end
91
+ end
73
92
  end
74
93
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bigdecimal"
4
+
5
+ module ActiveJob
6
+ module Serializers
7
+ class BigDecimalSerializer < ObjectSerializer # :nodoc:
8
+ def serialize(big_decimal)
9
+ super("value" => big_decimal.to_s)
10
+ end
11
+
12
+ def deserialize(hash)
13
+ BigDecimal(hash["value"])
14
+ end
15
+
16
+ private
17
+ def klass
18
+ BigDecimal
19
+ end
20
+ end
21
+ end
22
+ end
@@ -4,14 +4,16 @@ module ActiveJob
4
4
  module Serializers
5
5
  class DurationSerializer < ObjectSerializer # :nodoc:
6
6
  def serialize(duration)
7
+ # Ideally duration.parts would be wrapped in an array before passing to Arguments.serialize,
8
+ # but we continue passing the bare hash for backwards compatibility:
7
9
  super("value" => duration.value, "parts" => Arguments.serialize(duration.parts))
8
10
  end
9
11
 
10
12
  def deserialize(hash)
11
13
  value = hash["value"]
12
14
  parts = Arguments.deserialize(hash["parts"])
13
-
14
- klass.new(value, parts)
15
+ # `parts` is originally a hash, but will have been flattened to an array by Arguments.serialize
16
+ klass.new(value, parts.to_h)
15
17
  end
16
18
 
17
19
  private
@@ -3,7 +3,9 @@
3
3
  require "set"
4
4
 
5
5
  module ActiveJob
6
- # The <tt>ActiveJob::Serializers</tt> module is used to store a list of known serializers
6
+ # = Active Job \Serializers
7
+ #
8
+ # The +ActiveJob::Serializers+ module is used to store a list of known serializers
7
9
  # and to add new ones. It also has helpers to serialize/deserialize objects.
8
10
  module Serializers # :nodoc:
9
11
  extend ActiveSupport::Autoload
@@ -18,6 +20,7 @@ module ActiveJob
18
20
  autoload :TimeSerializer
19
21
  autoload :ModuleSerializer
20
22
  autoload :RangeSerializer
23
+ autoload :BigDecimalSerializer
21
24
 
22
25
  mattr_accessor :_additional_serializers
23
26
  self._additional_serializers = Set.new
@@ -25,7 +28,7 @@ module ActiveJob
25
28
  class << self
26
29
  # Returns serialized representative of the passed object.
27
30
  # Will look up through all known serializers.
28
- # Raises <tt>ActiveJob::SerializationError</tt> if it can't find a proper serializer.
31
+ # Raises ActiveJob::SerializationError if it can't find a proper serializer.
29
32
  def serialize(argument)
30
33
  serializer = serializers.detect { |s| s.serialize?(argument) }
31
34
  raise SerializationError.new("Unsupported argument type: #{argument.class.name}") unless serializer
@@ -63,6 +66,7 @@ module ActiveJob
63
66
  TimeWithZoneSerializer,
64
67
  TimeSerializer,
65
68
  ModuleSerializer,
66
- RangeSerializer
69
+ RangeSerializer,
70
+ BigDecimalSerializer
67
71
  end
68
72
  end
@@ -54,15 +54,10 @@ module ActiveJob
54
54
  queue_adapter_changed_jobs.each { |klass| klass.disable_test_adapter }
55
55
  end
56
56
 
57
- # Specifies the queue adapter to use with all Active Job test helpers.
58
- #
59
- # Returns an instance of the queue adapter and defaults to
60
- # ActiveJob::QueueAdapters::TestAdapter.
61
- #
62
- # Note: The adapter provided by this method must provide some additional
63
- # methods from those expected of a standard ActiveJob::QueueAdapter
64
- # in order to be used with the active job test helpers. Refer to
65
- # ActiveJob::QueueAdapters::TestAdapter.
57
+ # Returns a queue adapter instance to use with all Active Job test helpers.
58
+ # By default, returns an instance of ActiveJob::QueueAdapters::TestAdapter.
59
+ # Override this method to specify a different adapter. The adapter must
60
+ # implement the same interface as ActiveJob::QueueAdapters::TestAdapter.
66
61
  def queue_adapter_for_test
67
62
  ActiveJob::QueueAdapters::TestAdapter.new
68
63
  end
@@ -354,6 +349,13 @@ module ActiveJob
354
349
  # assert_enqueued_with(at: Date.tomorrow.noon, queue: "my_queue")
355
350
  # end
356
351
  #
352
+ # For keyword arguments, specify them as a hash inside an array:
353
+ #
354
+ # def test_assert_enqueued_with_keyword_arguments
355
+ # MyJob.perform_later(arg1: 'value1', arg2: 'value2')
356
+ # assert_enqueued_with(job: MyJob, args: [{ arg1: 'value1', arg2: 'value2' }])
357
+ # end
358
+ #
357
359
  # The given arguments may also be specified as matcher procs that return a
358
360
  # boolean value indicating whether a job's attribute meets certain criteria.
359
361
  #
@@ -593,11 +595,17 @@ module ActiveJob
593
595
  # assert_performed_jobs 1
594
596
  # end
595
597
  #
596
- # If the +:at+ option is specified, then only run jobs enqueued to run
597
- # immediately or before the given time
598
+ # If the +:at+ option is specified, then only jobs that have been enqueued
599
+ # to run at or before the given time will be performed. This includes jobs
600
+ # that have been enqueued without a time.
601
+ #
602
+ # If queue_adapter_for_test is overridden to return a different adapter,
603
+ # +perform_enqueued_jobs+ will merely execute the block.
598
604
  def perform_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil, &block)
599
605
  return flush_enqueued_jobs(only: only, except: except, queue: queue, at: at) unless block_given?
600
606
 
607
+ return _assert_nothing_raised_or_warn("perform_enqueued_jobs", &block) unless using_test_adapter?
608
+
601
609
  validate_option(only: only, except: except)
602
610
 
603
611
  old_perform_enqueued_jobs = queue_adapter.perform_enqueued_jobs
@@ -636,12 +644,16 @@ module ActiveJob
636
644
  end
637
645
 
638
646
  private
647
+ def using_test_adapter?
648
+ queue_adapter.is_a?(ActiveJob::QueueAdapters::TestAdapter)
649
+ end
650
+
639
651
  def clear_enqueued_jobs
640
- enqueued_jobs.clear
652
+ enqueued_jobs.clear if using_test_adapter?
641
653
  end
642
654
 
643
655
  def clear_performed_jobs
644
- performed_jobs.clear
656
+ performed_jobs.clear if using_test_adapter?
645
657
  end
646
658
 
647
659
  def jobs_with(jobs, only: nil, except: nil, queue: nil, at: nil)
@@ -694,6 +706,10 @@ module ActiveJob
694
706
 
695
707
  def prepare_args_for_assertion(args)
696
708
  args.dup.tap do |arguments|
709
+ if arguments[:queue].is_a?(Symbol)
710
+ arguments[:queue] = arguments[:queue].to_s
711
+ end
712
+
697
713
  if arguments[:at].acts_like?(:time)
698
714
  at_range = arguments[:at] - 1..arguments[:at] + 1
699
715
  arguments[:at] = ->(at) { at_range.cover?(at) }
@@ -3,7 +3,7 @@
3
3
  require_relative "gem_version"
4
4
 
5
5
  module ActiveJob
6
- # Returns the currently loaded version of Active Job as a <tt>Gem::Version</tt>.
6
+ # Returns the currently loaded version of Active Job as a +Gem::Version+.
7
7
  def self.version
8
8
  gem_version
9
9
  end
data/lib/active_job.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2014-2022 David Heinemeier Hansson
4
+ # Copyright (c) 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
@@ -26,16 +26,38 @@
26
26
  require "active_support"
27
27
  require "active_support/rails"
28
28
  require "active_job/version"
29
+ require "active_job/deprecator"
29
30
  require "global_id"
30
31
 
32
+ # :markup: markdown
33
+ # :include: activejob/README.md
31
34
  module ActiveJob
32
35
  extend ActiveSupport::Autoload
33
36
 
34
37
  autoload :Base
35
38
  autoload :QueueAdapters
36
- autoload :Serializers
37
- autoload :ConfiguredJob
39
+
40
+ eager_autoload do
41
+ autoload :Serializers
42
+ autoload :ConfiguredJob
43
+ end
44
+
38
45
  autoload :TestCase
39
46
  autoload :TestHelper
40
- autoload :QueryTags
47
+
48
+ ##
49
+ # :singleton-method:
50
+ # If false, \Rails will preserve the legacy serialization of BigDecimal job arguments as Strings.
51
+ # If true, \Rails will use the new BigDecimalSerializer to (de)serialize BigDecimal losslessly.
52
+ # Legacy serialization will be removed in \Rails 7.2, along with this config.
53
+ singleton_class.attr_accessor :use_big_decimal_serializer
54
+ self.use_big_decimal_serializer = false
55
+
56
+ ##
57
+ # :singleton-method:
58
+ #
59
+ # Specifies if the methods calling background job enqueue should be logged below
60
+ # their relevant enqueue log lines. Defaults to false.
61
+ singleton_class.attr_accessor :verbose_enqueue_logs
62
+ self.verbose_enqueue_logs = false
41
63
  end
@@ -0,0 +1,19 @@
1
+ Description:
2
+ Generates a new job. Pass the job name, either CamelCased or
3
+ under_scored, with or without the job postfix.
4
+
5
+ Examples:
6
+ `bin/rails generate job checkout`
7
+
8
+ Creates the following files:
9
+
10
+ Job: app/jobs/checkout_job.rb
11
+ Test: test/jobs/checkout_job_test.rb
12
+
13
+ `bin/rails generate job send_sms --queue=sms`
14
+
15
+ Creates a job and test with a custom sms queue.
16
+
17
+ `bin/rails generate job process_payment --parent=payment_job`
18
+
19
+ Creates a job and test with a `PaymentJob` parent class.
@@ -5,10 +5,10 @@ require "rails/generators/named_base"
5
5
  module Rails # :nodoc:
6
6
  module Generators # :nodoc:
7
7
  class JobGenerator < Rails::Generators::NamedBase # :nodoc:
8
- desc "This generator creates an active job file at app/jobs"
9
-
10
8
  class_option :queue, type: :string, default: "default", desc: "The queue name for the generated job"
11
9
 
10
+ class_option :parent, type: :string, default: "ApplicationJob", desc: "The parent class for the generated job"
11
+
12
12
  check_class_collision suffix: "Job"
13
13
 
14
14
  hook_for :test_framework
@@ -28,6 +28,10 @@ module Rails # :nodoc:
28
28
  end
29
29
 
30
30
  private
31
+ def parent_class_name
32
+ options[:parent]
33
+ end
34
+
31
35
  def file_name
32
36
  @_file_name ||= super.sub(/_job\z/i, "")
33
37
  end
@@ -1,5 +1,5 @@
1
1
  <% module_namespacing do -%>
2
- class <%= class_name %>Job < ApplicationJob
2
+ class <%= class_name %>Job < <%= parent_class_name.classify %>
3
3
  queue_as :<%= options[:queue] %>
4
4
 
5
5
  def perform(*args)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activejob
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.8
4
+ version: 7.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-09 00:00:00.000000000 Z
11
+ date: 2023-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 7.0.8
19
+ version: 7.1.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 7.0.8
26
+ version: 7.1.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: globalid
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -53,6 +53,7 @@ files:
53
53
  - lib/active_job/callbacks.rb
54
54
  - lib/active_job/configured_job.rb
55
55
  - lib/active_job/core.rb
56
+ - lib/active_job/deprecator.rb
56
57
  - lib/active_job/enqueuing.rb
57
58
  - lib/active_job/exceptions.rb
58
59
  - lib/active_job/execution.rb
@@ -66,7 +67,6 @@ files:
66
67
  - lib/active_job/queue_adapters/backburner_adapter.rb
67
68
  - lib/active_job/queue_adapters/delayed_job_adapter.rb
68
69
  - lib/active_job/queue_adapters/inline_adapter.rb
69
- - lib/active_job/queue_adapters/que_adapter.rb
70
70
  - lib/active_job/queue_adapters/queue_classic_adapter.rb
71
71
  - lib/active_job/queue_adapters/resque_adapter.rb
72
72
  - lib/active_job/queue_adapters/sidekiq_adapter.rb
@@ -77,6 +77,7 @@ files:
77
77
  - lib/active_job/queue_priority.rb
78
78
  - lib/active_job/railtie.rb
79
79
  - lib/active_job/serializers.rb
80
+ - lib/active_job/serializers/big_decimal_serializer.rb
80
81
  - lib/active_job/serializers/date_serializer.rb
81
82
  - lib/active_job/serializers/date_time_serializer.rb
82
83
  - lib/active_job/serializers/duration_serializer.rb
@@ -92,6 +93,7 @@ files:
92
93
  - lib/active_job/timezones.rb
93
94
  - lib/active_job/translation.rb
94
95
  - lib/active_job/version.rb
96
+ - lib/rails/generators/job/USAGE
95
97
  - lib/rails/generators/job/job_generator.rb
96
98
  - lib/rails/generators/job/templates/application_job.rb.tt
97
99
  - lib/rails/generators/job/templates/job.rb.tt
@@ -100,10 +102,10 @@ licenses:
100
102
  - MIT
101
103
  metadata:
102
104
  bug_tracker_uri: https://github.com/rails/rails/issues
103
- changelog_uri: https://github.com/rails/rails/blob/v7.0.8/activejob/CHANGELOG.md
104
- documentation_uri: https://api.rubyonrails.org/v7.0.8/
105
+ changelog_uri: https://github.com/rails/rails/blob/v7.1.1/activejob/CHANGELOG.md
106
+ documentation_uri: https://api.rubyonrails.org/v7.1.1/
105
107
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
106
- source_code_uri: https://github.com/rails/rails/tree/v7.0.8/activejob
108
+ source_code_uri: https://github.com/rails/rails/tree/v7.1.1/activejob
107
109
  rubygems_mfa_required: 'true'
108
110
  post_install_message:
109
111
  rdoc_options: []
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "que"
4
-
5
- module ActiveJob
6
- module QueueAdapters
7
- # == Que adapter for Active Job
8
- #
9
- # Que is a high-performance alternative to DelayedJob or QueueClassic that
10
- # improves the reliability of your application by protecting your jobs with
11
- # the same ACID guarantees as the rest of your data. Que is a queue for
12
- # Ruby and PostgreSQL that manages jobs using advisory locks.
13
- #
14
- # Read more about Que {here}[https://github.com/chanks/que].
15
- #
16
- # To use Que set the queue_adapter config to +:que+.
17
- #
18
- # Rails.application.config.active_job.queue_adapter = :que
19
- class QueAdapter
20
- def enqueue(job) # :nodoc:
21
- job_options = { priority: job.priority, queue: job.queue_name }
22
- que_job = nil
23
-
24
- if require_job_options_kwarg?
25
- que_job = JobWrapper.enqueue job.serialize, job_options: job_options
26
- else
27
- que_job = JobWrapper.enqueue job.serialize, **job_options
28
- end
29
-
30
- job.provider_job_id = que_job.attrs["job_id"]
31
- que_job
32
- end
33
-
34
- def enqueue_at(job, timestamp) # :nodoc:
35
- job_options = { priority: job.priority, queue: job.queue_name, run_at: Time.at(timestamp) }
36
- que_job = nil
37
-
38
- if require_job_options_kwarg?
39
- que_job = JobWrapper.enqueue job.serialize, job_options: job_options
40
- else
41
- que_job = JobWrapper.enqueue job.serialize, **job_options
42
- end
43
-
44
- job.provider_job_id = que_job.attrs["job_id"]
45
- que_job
46
- end
47
-
48
- private
49
- def require_job_options_kwarg?
50
- @require_job_options_kwarg ||=
51
- JobWrapper.method(:enqueue).parameters.any? { |ptype, pname| ptype == :key && pname == :job_options }
52
- end
53
-
54
- class JobWrapper < Que::Job # :nodoc:
55
- def run(job_data)
56
- Base.execute job_data
57
- end
58
- end
59
- end
60
- end
61
- end