activejob 5.2.2.1 → 6.0.2
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.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +128 -32
 - data/MIT-LICENSE +1 -1
 - data/README.md +17 -10
 - data/lib/active_job.rb +2 -1
 - data/lib/active_job/arguments.rb +40 -28
 - data/lib/active_job/base.rb +3 -1
 - data/lib/active_job/callbacks.rb +4 -1
 - data/lib/active_job/core.rb +38 -21
 - data/lib/active_job/enqueuing.rb +26 -5
 - data/lib/active_job/exceptions.rb +40 -17
 - data/lib/active_job/execution.rb +1 -1
 - data/lib/active_job/gem_version.rb +3 -3
 - data/lib/active_job/logging.rb +40 -9
 - data/lib/active_job/queue_adapter.rb +2 -0
 - data/lib/active_job/queue_adapters.rb +8 -10
 - data/lib/active_job/queue_adapters/async_adapter.rb +1 -1
 - data/lib/active_job/queue_adapters/backburner_adapter.rb +2 -2
 - data/lib/active_job/queue_adapters/inline_adapter.rb +1 -1
 - data/lib/active_job/queue_adapters/sidekiq_adapter.rb +2 -2
 - data/lib/active_job/queue_adapters/test_adapter.rb +22 -8
 - data/lib/active_job/queue_name.rb +21 -1
 - data/lib/active_job/railtie.rb +16 -1
 - data/lib/active_job/serializers.rb +63 -0
 - data/lib/active_job/serializers/date_serializer.rb +21 -0
 - data/lib/active_job/serializers/date_time_serializer.rb +21 -0
 - data/lib/active_job/serializers/duration_serializer.rb +24 -0
 - data/lib/active_job/serializers/object_serializer.rb +54 -0
 - data/lib/active_job/serializers/symbol_serializer.rb +21 -0
 - data/lib/active_job/serializers/time_serializer.rb +21 -0
 - data/lib/active_job/serializers/time_with_zone_serializer.rb +21 -0
 - data/lib/active_job/test_helper.rb +278 -57
 - data/lib/active_job/timezones.rb +13 -0
 - data/lib/active_job/translation.rb +1 -1
 - data/lib/rails/generators/job/job_generator.rb +4 -0
 - metadata +22 -11
 - data/lib/active_job/queue_adapters/qu_adapter.rb +0 -46
 
    
        data/lib/active_job/callbacks.rb
    CHANGED
    
    | 
         @@ -29,6 +29,9 @@ module ActiveJob 
     | 
|
| 
       29 
29 
     | 
    
         
             
                included do
         
     | 
| 
       30 
30 
     | 
    
         
             
                  define_callbacks :perform
         
     | 
| 
       31 
31 
     | 
    
         
             
                  define_callbacks :enqueue
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  class_attribute :return_false_on_aborted_enqueue, instance_accessor: false, instance_predicate: false
         
     | 
| 
      
 34 
     | 
    
         
            +
                  self.return_false_on_aborted_enqueue = false
         
     | 
| 
       32 
35 
     | 
    
         
             
                end
         
     | 
| 
       33 
36 
     | 
    
         | 
| 
       34 
37 
     | 
    
         
             
                # These methods will be included into any Active Job object, adding
         
     | 
| 
         @@ -130,7 +133,7 @@ module ActiveJob 
     | 
|
| 
       130 
133 
     | 
    
         
             
                    set_callback(:enqueue, :after, *filters, &blk)
         
     | 
| 
       131 
134 
     | 
    
         
             
                  end
         
     | 
| 
       132 
135 
     | 
    
         | 
| 
       133 
     | 
    
         
            -
                  # Defines a callback that will get called around the  
     | 
| 
      
 136 
     | 
    
         
            +
                  # Defines a callback that will get called around the enqueuing
         
     | 
| 
       134 
137 
     | 
    
         
             
                  # of the job.
         
     | 
| 
       135 
138 
     | 
    
         
             
                  #
         
     | 
| 
       136 
139 
     | 
    
         
             
                  #   class VideoProcessJob < ActiveJob::Base
         
     | 
    
        data/lib/active_job/core.rb
    CHANGED
    
    | 
         @@ -6,32 +6,42 @@ module ActiveJob 
     | 
|
| 
       6 
6 
     | 
    
         
             
              module Core
         
     | 
| 
       7 
7 
     | 
    
         
             
                extend ActiveSupport::Concern
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                 
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                  attr_writer :serialized_arguments
         
     | 
| 
      
 9 
     | 
    
         
            +
                # Job arguments
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_accessor :arguments
         
     | 
| 
      
 11 
     | 
    
         
            +
                attr_writer :serialized_arguments
         
     | 
| 
       13 
12 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
      
 13 
     | 
    
         
            +
                # Timestamp when the job should be performed
         
     | 
| 
      
 14 
     | 
    
         
            +
                attr_accessor :scheduled_at
         
     | 
| 
       16 
15 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
      
 16 
     | 
    
         
            +
                # Job Identifier
         
     | 
| 
      
 17 
     | 
    
         
            +
                attr_accessor :job_id
         
     | 
| 
       19 
18 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 19 
     | 
    
         
            +
                # Queue in which the job will reside.
         
     | 
| 
      
 20 
     | 
    
         
            +
                attr_writer :queue_name
         
     | 
| 
       22 
21 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
      
 22 
     | 
    
         
            +
                # Priority that the job will have (lower is more priority).
         
     | 
| 
      
 23 
     | 
    
         
            +
                attr_writer :priority
         
     | 
| 
       25 
24 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
      
 25 
     | 
    
         
            +
                # ID optionally provided by adapter
         
     | 
| 
      
 26 
     | 
    
         
            +
                attr_accessor :provider_job_id
         
     | 
| 
       28 
27 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
      
 28 
     | 
    
         
            +
                # Number of times this job has been executed (which increments on every retry, like after an exception).
         
     | 
| 
      
 29 
     | 
    
         
            +
                attr_accessor :executions
         
     | 
| 
       31 
30 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
                 
     | 
| 
      
 31 
     | 
    
         
            +
                # Hash that contains the number of times this job handled errors for each specific retry_on declaration.
         
     | 
| 
      
 32 
     | 
    
         
            +
                # Keys are the string representation of the exceptions listed in the retry_on declaration,
         
     | 
| 
      
 33 
     | 
    
         
            +
                # while its associated value holds the number of executions where the corresponding retry_on
         
     | 
| 
      
 34 
     | 
    
         
            +
                # declaration handled one of its listed exceptions.
         
     | 
| 
      
 35 
     | 
    
         
            +
                attr_accessor :exception_executions
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                # I18n.locale to be used during the job.
         
     | 
| 
      
 38 
     | 
    
         
            +
                attr_accessor :locale
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                # Timezone to be used during the job.
         
     | 
| 
      
 41 
     | 
    
         
            +
                attr_accessor :timezone
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                # Track when a job was enqueued
         
     | 
| 
      
 44 
     | 
    
         
            +
                attr_accessor :enqueued_at
         
     | 
| 
       35 
45 
     | 
    
         | 
| 
       36 
46 
     | 
    
         
             
                # These methods will be included into any Active Job object, adding
         
     | 
| 
       37 
47 
     | 
    
         
             
                # helpers for de/serialization and creation of job instances.
         
     | 
| 
         @@ -74,10 +84,11 @@ module ActiveJob 
     | 
|
| 
       74 
84 
     | 
    
         
             
                  @queue_name = self.class.queue_name
         
     | 
| 
       75 
85 
     | 
    
         
             
                  @priority   = self.class.priority
         
     | 
| 
       76 
86 
     | 
    
         
             
                  @executions = 0
         
     | 
| 
      
 87 
     | 
    
         
            +
                  @exception_executions = {}
         
     | 
| 
       77 
88 
     | 
    
         
             
                end
         
     | 
| 
       78 
89 
     | 
    
         | 
| 
       79 
90 
     | 
    
         
             
                # Returns a hash with the job data that can safely be passed to the
         
     | 
| 
       80 
     | 
    
         
            -
                #  
     | 
| 
      
 91 
     | 
    
         
            +
                # queuing adapter.
         
     | 
| 
       81 
92 
     | 
    
         
             
                def serialize
         
     | 
| 
       82 
93 
     | 
    
         
             
                  {
         
     | 
| 
       83 
94 
     | 
    
         
             
                    "job_class"  => self.class.name,
         
     | 
| 
         @@ -87,7 +98,10 @@ module ActiveJob 
     | 
|
| 
       87 
98 
     | 
    
         
             
                    "priority"   => priority,
         
     | 
| 
       88 
99 
     | 
    
         
             
                    "arguments"  => serialize_arguments_if_needed(arguments),
         
     | 
| 
       89 
100 
     | 
    
         
             
                    "executions" => executions,
         
     | 
| 
       90 
     | 
    
         
            -
                    " 
     | 
| 
      
 101 
     | 
    
         
            +
                    "exception_executions" => exception_executions,
         
     | 
| 
      
 102 
     | 
    
         
            +
                    "locale"     => I18n.locale.to_s,
         
     | 
| 
      
 103 
     | 
    
         
            +
                    "timezone"   => Time.zone.try(:name),
         
     | 
| 
      
 104 
     | 
    
         
            +
                    "enqueued_at" => Time.now.utc.iso8601
         
     | 
| 
       91 
105 
     | 
    
         
             
                  }
         
     | 
| 
       92 
106 
     | 
    
         
             
                end
         
     | 
| 
       93 
107 
     | 
    
         | 
| 
         @@ -124,7 +138,10 @@ module ActiveJob 
     | 
|
| 
       124 
138 
     | 
    
         
             
                  self.priority             = job_data["priority"]
         
     | 
| 
       125 
139 
     | 
    
         
             
                  self.serialized_arguments = job_data["arguments"]
         
     | 
| 
       126 
140 
     | 
    
         
             
                  self.executions           = job_data["executions"]
         
     | 
| 
      
 141 
     | 
    
         
            +
                  self.exception_executions = job_data["exception_executions"]
         
     | 
| 
       127 
142 
     | 
    
         
             
                  self.locale               = job_data["locale"] || I18n.locale.to_s
         
     | 
| 
      
 143 
     | 
    
         
            +
                  self.timezone             = job_data["timezone"] || Time.zone.try(:name)
         
     | 
| 
      
 144 
     | 
    
         
            +
                  self.enqueued_at          = job_data["enqueued_at"]
         
     | 
| 
       128 
145 
     | 
    
         
             
                end
         
     | 
| 
       129 
146 
     | 
    
         | 
| 
       130 
147 
     | 
    
         
             
                private
         
     | 
    
        data/lib/active_job/enqueuing.rb
    CHANGED
    
    | 
         @@ -9,10 +9,12 @@ module ActiveJob 
     | 
|
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                # Includes the +perform_later+ method for job initialization.
         
     | 
| 
       11 
11 
     | 
    
         
             
                module ClassMethods
         
     | 
| 
       12 
     | 
    
         
            -
                  # Push a job onto the queue.  
     | 
| 
       13 
     | 
    
         
            -
                  #  
     | 
| 
       14 
     | 
    
         
            -
                  #  
     | 
| 
       15 
     | 
    
         
            -
                  #  
     | 
| 
      
 12 
     | 
    
         
            +
                  # Push a job onto the queue. By default the arguments must be either String,
         
     | 
| 
      
 13 
     | 
    
         
            +
                  # Integer, Float, NilClass, TrueClass, FalseClass, BigDecimal, Symbol, Date,
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # Time, DateTime, ActiveSupport::TimeWithZone, ActiveSupport::Duration,
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # Hash, ActiveSupport::HashWithIndifferentAccess, Array or
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # GlobalID::Identification instances, although this can be extended by adding
         
     | 
| 
      
 17 
     | 
    
         
            +
                  # custom serializers.
         
     | 
| 
       16 
18 
     | 
    
         
             
                  #
         
     | 
| 
       17 
19 
     | 
    
         
             
                  # Returns an instance of the job class queued with arguments available in
         
     | 
| 
       18 
20 
     | 
    
         
             
                  # Job#arguments.
         
     | 
| 
         @@ -46,14 +48,33 @@ module ActiveJob 
     | 
|
| 
       46 
48 
     | 
    
         
             
                  self.scheduled_at = options[:wait_until].to_f if options[:wait_until]
         
     | 
| 
       47 
49 
     | 
    
         
             
                  self.queue_name   = self.class.queue_name_from_part(options[:queue]) if options[:queue]
         
     | 
| 
       48 
50 
     | 
    
         
             
                  self.priority     = options[:priority].to_i if options[:priority]
         
     | 
| 
      
 51 
     | 
    
         
            +
                  successfully_enqueued = false
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
       49 
53 
     | 
    
         
             
                  run_callbacks :enqueue do
         
     | 
| 
       50 
54 
     | 
    
         
             
                    if scheduled_at
         
     | 
| 
       51 
55 
     | 
    
         
             
                      self.class.queue_adapter.enqueue_at self, scheduled_at
         
     | 
| 
       52 
56 
     | 
    
         
             
                    else
         
     | 
| 
       53 
57 
     | 
    
         
             
                      self.class.queue_adapter.enqueue self
         
     | 
| 
       54 
58 
     | 
    
         
             
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    successfully_enqueued = true
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  if successfully_enqueued
         
     | 
| 
      
 64 
     | 
    
         
            +
                    self
         
     | 
| 
      
 65 
     | 
    
         
            +
                  else
         
     | 
| 
      
 66 
     | 
    
         
            +
                    if self.class.return_false_on_aborted_enqueue
         
     | 
| 
      
 67 
     | 
    
         
            +
                      false
         
     | 
| 
      
 68 
     | 
    
         
            +
                    else
         
     | 
| 
      
 69 
     | 
    
         
            +
                      ActiveSupport::Deprecation.warn(
         
     | 
| 
      
 70 
     | 
    
         
            +
                        "Rails 6.1 will return false when the enqueuing is aborted. Make sure your code doesn't depend on it" \
         
     | 
| 
      
 71 
     | 
    
         
            +
                        " returning the instance of the job and set `config.active_job.return_false_on_aborted_enqueue = true`" \
         
     | 
| 
      
 72 
     | 
    
         
            +
                        " to remove the deprecations."
         
     | 
| 
      
 73 
     | 
    
         
            +
                      )
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                      self
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
       55 
77 
     | 
    
         
             
                  end
         
     | 
| 
       56 
     | 
    
         
            -
                  self
         
     | 
| 
       57 
78 
     | 
    
         
             
                end
         
     | 
| 
       58 
79 
     | 
    
         
             
              end
         
     | 
| 
       59 
80 
     | 
    
         
             
            end
         
     | 
| 
         @@ -30,28 +30,36 @@ module ActiveJob 
     | 
|
| 
       30 
30 
     | 
    
         
             
                  #  class RemoteServiceJob < ActiveJob::Base
         
     | 
| 
       31 
31 
     | 
    
         
             
                  #    retry_on CustomAppException # defaults to 3s wait, 5 attempts
         
     | 
| 
       32 
32 
     | 
    
         
             
                  #    retry_on AnotherCustomAppException, wait: ->(executions) { executions * 2 }
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #
         
     | 
| 
      
 34 
     | 
    
         
            +
                  #    retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3
         
     | 
| 
      
 35 
     | 
    
         
            +
                  #    retry_on Net::OpenTimeout, Timeout::Error, wait: :exponentially_longer, attempts: 10 # retries at most 10 times for Net::OpenTimeout and Timeout::Error combined
         
     | 
| 
      
 36 
     | 
    
         
            +
                  #    # To retry at most 10 times for each individual exception:
         
     | 
| 
      
 37 
     | 
    
         
            +
                  #    # retry_on Net::OpenTimeout, wait: :exponentially_longer, attempts: 10
         
     | 
| 
      
 38 
     | 
    
         
            +
                  #    # retry_on Timeout::Error, wait: :exponentially_longer, attempts: 10
         
     | 
| 
      
 39 
     | 
    
         
            +
                  #
         
     | 
| 
       33 
40 
     | 
    
         
             
                  #    retry_on(YetAnotherCustomAppException) do |job, error|
         
     | 
| 
       34 
41 
     | 
    
         
             
                  #      ExceptionNotifier.caught(error)
         
     | 
| 
       35 
42 
     | 
    
         
             
                  #    end
         
     | 
| 
       36 
     | 
    
         
            -
                  #    retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3
         
     | 
| 
       37 
     | 
    
         
            -
                  #    retry_on Net::OpenTimeout, wait: :exponentially_longer, attempts: 10
         
     | 
| 
       38 
43 
     | 
    
         
             
                  #
         
     | 
| 
       39 
44 
     | 
    
         
             
                  #    def perform(*args)
         
     | 
| 
       40 
45 
     | 
    
         
             
                  #      # Might raise CustomAppException, AnotherCustomAppException, or YetAnotherCustomAppException for something domain specific
         
     | 
| 
       41 
46 
     | 
    
         
             
                  #      # Might raise ActiveRecord::Deadlocked when a local db deadlock is detected
         
     | 
| 
       42 
     | 
    
         
            -
                  #      # Might raise Net::OpenTimeout when the remote service is down
         
     | 
| 
      
 47 
     | 
    
         
            +
                  #      # Might raise Net::OpenTimeout or Timeout::Error when the remote service is down
         
     | 
| 
       43 
48 
     | 
    
         
             
                  #    end
         
     | 
| 
       44 
49 
     | 
    
         
             
                  #  end
         
     | 
| 
       45 
     | 
    
         
            -
                  def retry_on( 
     | 
| 
       46 
     | 
    
         
            -
                    rescue_from  
     | 
| 
      
 50 
     | 
    
         
            +
                  def retry_on(*exceptions, wait: 3.seconds, attempts: 5, queue: nil, priority: nil)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    rescue_from(*exceptions) do |error|
         
     | 
| 
      
 52 
     | 
    
         
            +
                      executions = executions_for(exceptions)
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
       47 
54 
     | 
    
         
             
                      if executions < attempts
         
     | 
| 
       48 
     | 
    
         
            -
                         
     | 
| 
       49 
     | 
    
         
            -
                        retry_job wait: determine_delay(wait), queue: queue, priority: priority
         
     | 
| 
      
 55 
     | 
    
         
            +
                        retry_job wait: determine_delay(seconds_or_duration_or_algorithm: wait, executions: executions), queue: queue, priority: priority, error: error
         
     | 
| 
       50 
56 
     | 
    
         
             
                      else
         
     | 
| 
       51 
57 
     | 
    
         
             
                        if block_given?
         
     | 
| 
       52 
     | 
    
         
            -
                           
     | 
| 
      
 58 
     | 
    
         
            +
                          instrument :retry_stopped, error: error do
         
     | 
| 
      
 59 
     | 
    
         
            +
                            yield self, error
         
     | 
| 
      
 60 
     | 
    
         
            +
                          end
         
     | 
| 
       53 
61 
     | 
    
         
             
                        else
         
     | 
| 
       54 
     | 
    
         
            -
                           
     | 
| 
      
 62 
     | 
    
         
            +
                          instrument :retry_stopped, error: error
         
     | 
| 
       55 
63 
     | 
    
         
             
                          raise error
         
     | 
| 
       56 
64 
     | 
    
         
             
                        end
         
     | 
| 
       57 
65 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -76,12 +84,10 @@ module ActiveJob 
     | 
|
| 
       76 
84 
     | 
    
         
             
                  #      # Might raise CustomAppException for something domain specific
         
     | 
| 
       77 
85 
     | 
    
         
             
                  #    end
         
     | 
| 
       78 
86 
     | 
    
         
             
                  #  end
         
     | 
| 
       79 
     | 
    
         
            -
                  def discard_on( 
     | 
| 
       80 
     | 
    
         
            -
                    rescue_from  
     | 
| 
       81 
     | 
    
         
            -
                       
     | 
| 
       82 
     | 
    
         
            -
                        yield self, error
         
     | 
| 
       83 
     | 
    
         
            -
                      else
         
     | 
| 
       84 
     | 
    
         
            -
                        logger.error "Discarded #{self.class} due to a #{exception}. The original exception was #{error.cause.inspect}."
         
     | 
| 
      
 87 
     | 
    
         
            +
                  def discard_on(*exceptions)
         
     | 
| 
      
 88 
     | 
    
         
            +
                    rescue_from(*exceptions) do |error|
         
     | 
| 
      
 89 
     | 
    
         
            +
                      instrument :discard, error: error do
         
     | 
| 
      
 90 
     | 
    
         
            +
                        yield self, error if block_given?
         
     | 
| 
       85 
91 
     | 
    
         
             
                      end
         
     | 
| 
       86 
92 
     | 
    
         
             
                    end
         
     | 
| 
       87 
93 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -109,11 +115,13 @@ module ActiveJob 
     | 
|
| 
       109 
115 
     | 
    
         
             
                #    end
         
     | 
| 
       110 
116 
     | 
    
         
             
                #  end
         
     | 
| 
       111 
117 
     | 
    
         
             
                def retry_job(options = {})
         
     | 
| 
       112 
     | 
    
         
            -
                   
     | 
| 
      
 118 
     | 
    
         
            +
                  instrument :enqueue_retry, options.slice(:error, :wait) do
         
     | 
| 
      
 119 
     | 
    
         
            +
                    enqueue options
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
       113 
121 
     | 
    
         
             
                end
         
     | 
| 
       114 
122 
     | 
    
         | 
| 
       115 
123 
     | 
    
         
             
                private
         
     | 
| 
       116 
     | 
    
         
            -
                  def determine_delay(seconds_or_duration_or_algorithm)
         
     | 
| 
      
 124 
     | 
    
         
            +
                  def determine_delay(seconds_or_duration_or_algorithm:, executions:)
         
     | 
| 
       117 
125 
     | 
    
         
             
                    case seconds_or_duration_or_algorithm
         
     | 
| 
       118 
126 
     | 
    
         
             
                    when :exponentially_longer
         
     | 
| 
       119 
127 
     | 
    
         
             
                      (executions**4) + 2
         
     | 
| 
         @@ -130,5 +138,20 @@ module ActiveJob 
     | 
|
| 
       130 
138 
     | 
    
         
             
                      raise "Couldn't determine a delay based on #{seconds_or_duration_or_algorithm.inspect}"
         
     | 
| 
       131 
139 
     | 
    
         
             
                    end
         
     | 
| 
       132 
140 
     | 
    
         
             
                  end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                  def instrument(name, error: nil, wait: nil, &block)
         
     | 
| 
      
 143 
     | 
    
         
            +
                    payload = { job: self, adapter: self.class.queue_adapter, error: error, wait: wait }
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                    ActiveSupport::Notifications.instrument("#{name}.active_job", payload, &block)
         
     | 
| 
      
 146 
     | 
    
         
            +
                  end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                  def executions_for(exceptions)
         
     | 
| 
      
 149 
     | 
    
         
            +
                    if exception_executions
         
     | 
| 
      
 150 
     | 
    
         
            +
                      exception_executions[exceptions.to_s] = (exception_executions[exceptions.to_s] || 0) + 1
         
     | 
| 
      
 151 
     | 
    
         
            +
                    else
         
     | 
| 
      
 152 
     | 
    
         
            +
                      # Guard against jobs that were persisted before we started having individual executions counters per retry_on
         
     | 
| 
      
 153 
     | 
    
         
            +
                      executions
         
     | 
| 
      
 154 
     | 
    
         
            +
                    end
         
     | 
| 
      
 155 
     | 
    
         
            +
                  end
         
     | 
| 
       133 
156 
     | 
    
         
             
              end
         
     | 
| 
       134 
157 
     | 
    
         
             
            end
         
     | 
    
        data/lib/active_job/execution.rb
    CHANGED
    
    | 
         @@ -26,7 +26,7 @@ module ActiveJob 
     | 
|
| 
       26 
26 
     | 
    
         
             
                  end
         
     | 
| 
       27 
27 
     | 
    
         
             
                end
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
                # Performs the job immediately. The job is not sent to the  
     | 
| 
      
 29 
     | 
    
         
            +
                # Performs the job immediately. The job is not sent to the queuing adapter
         
     | 
| 
       30 
30 
     | 
    
         
             
                # but directly executed by blocking the execution of others until it's finished.
         
     | 
| 
       31 
31 
     | 
    
         
             
                #
         
     | 
| 
       32 
32 
     | 
    
         
             
                #   MyJob.new(*args).perform_now
         
     | 
    
        data/lib/active_job/logging.rb
    CHANGED
    
    | 
         @@ -1,6 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            require "active_support/core_ext/hash/transform_values"
         
     | 
| 
       4 
3 
     | 
    
         
             
            require "active_support/core_ext/string/filters"
         
     | 
| 
       5 
4 
     | 
    
         
             
            require "active_support/tagged_logging"
         
     | 
| 
       6 
5 
     | 
    
         
             
            require "active_support/logger"
         
     | 
| 
         @@ -12,13 +11,13 @@ module ActiveJob 
     | 
|
| 
       12 
11 
     | 
    
         
             
                included do
         
     | 
| 
       13 
12 
     | 
    
         
             
                  cattr_accessor :logger, default: ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT))
         
     | 
| 
       14 
13 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
                  around_enqueue do |_, block 
     | 
| 
      
 14 
     | 
    
         
            +
                  around_enqueue do |_, block|
         
     | 
| 
       16 
15 
     | 
    
         
             
                    tag_logger do
         
     | 
| 
       17 
16 
     | 
    
         
             
                      block.call
         
     | 
| 
       18 
17 
     | 
    
         
             
                    end
         
     | 
| 
       19 
18 
     | 
    
         
             
                  end
         
     | 
| 
       20 
19 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                  around_perform do |job, block 
     | 
| 
      
 20 
     | 
    
         
            +
                  around_perform do |job, block|
         
     | 
| 
       22 
21 
     | 
    
         
             
                    tag_logger(job.class.name, job.job_id) do
         
     | 
| 
       23 
22 
     | 
    
         
             
                      payload = { adapter: job.class.queue_adapter, job: job }
         
     | 
| 
       24 
23 
     | 
    
         
             
                      ActiveSupport::Notifications.instrument("perform_start.active_job", payload.dup)
         
     | 
| 
         @@ -28,13 +27,13 @@ module ActiveJob 
     | 
|
| 
       28 
27 
     | 
    
         
             
                    end
         
     | 
| 
       29 
28 
     | 
    
         
             
                  end
         
     | 
| 
       30 
29 
     | 
    
         | 
| 
       31 
     | 
    
         
            -
                   
     | 
| 
      
 30 
     | 
    
         
            +
                  around_enqueue do |job, block|
         
     | 
| 
       32 
31 
     | 
    
         
             
                    if job.scheduled_at
         
     | 
| 
       33 
     | 
    
         
            -
                      ActiveSupport::Notifications.instrument 
     | 
| 
       34 
     | 
    
         
            -
                        adapter: job.class.queue_adapter, job: job
         
     | 
| 
      
 32 
     | 
    
         
            +
                      ActiveSupport::Notifications.instrument("enqueue_at.active_job",
         
     | 
| 
      
 33 
     | 
    
         
            +
                        adapter: job.class.queue_adapter, job: job, &block)
         
     | 
| 
       35 
34 
     | 
    
         
             
                    else
         
     | 
| 
       36 
     | 
    
         
            -
                      ActiveSupport::Notifications.instrument 
     | 
| 
       37 
     | 
    
         
            -
                        adapter: job.class.queue_adapter, job: job
         
     | 
| 
      
 35 
     | 
    
         
            +
                      ActiveSupport::Notifications.instrument("enqueue.active_job",
         
     | 
| 
      
 36 
     | 
    
         
            +
                        adapter: job.class.queue_adapter, job: job, &block)
         
     | 
| 
       38 
37 
     | 
    
         
             
                    end
         
     | 
| 
       39 
38 
     | 
    
         
             
                  end
         
     | 
| 
       40 
39 
     | 
    
         
             
                end
         
     | 
| 
         @@ -71,7 +70,7 @@ module ActiveJob 
     | 
|
| 
       71 
70 
     | 
    
         
             
                    def perform_start(event)
         
     | 
| 
       72 
71 
     | 
    
         
             
                      info do
         
     | 
| 
       73 
72 
     | 
    
         
             
                        job = event.payload[:job]
         
     | 
| 
       74 
     | 
    
         
            -
                        "Performing #{job.class.name} (Job ID: #{job.job_id}) from #{queue_name(event)}" + args_info(job)
         
     | 
| 
      
 73 
     | 
    
         
            +
                        "Performing #{job.class.name} (Job ID: #{job.job_id}) from #{queue_name(event)} enqueued at #{job.enqueued_at}" + args_info(job)
         
     | 
| 
       75 
74 
     | 
    
         
             
                      end
         
     | 
| 
       76 
75 
     | 
    
         
             
                    end
         
     | 
| 
       77 
76 
     | 
    
         | 
| 
         @@ -89,6 +88,38 @@ module ActiveJob 
     | 
|
| 
       89 
88 
     | 
    
         
             
                      end
         
     | 
| 
       90 
89 
     | 
    
         
             
                    end
         
     | 
| 
       91 
90 
     | 
    
         | 
| 
      
 91 
     | 
    
         
            +
                    def enqueue_retry(event)
         
     | 
| 
      
 92 
     | 
    
         
            +
                      job = event.payload[:job]
         
     | 
| 
      
 93 
     | 
    
         
            +
                      ex = event.payload[:error]
         
     | 
| 
      
 94 
     | 
    
         
            +
                      wait = event.payload[:wait]
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                      info do
         
     | 
| 
      
 97 
     | 
    
         
            +
                        if ex
         
     | 
| 
      
 98 
     | 
    
         
            +
                          "Retrying #{job.class} in #{wait.to_i} seconds, due to a #{ex.class}."
         
     | 
| 
      
 99 
     | 
    
         
            +
                        else
         
     | 
| 
      
 100 
     | 
    
         
            +
                          "Retrying #{job.class} in #{wait.to_i} seconds."
         
     | 
| 
      
 101 
     | 
    
         
            +
                        end
         
     | 
| 
      
 102 
     | 
    
         
            +
                      end
         
     | 
| 
      
 103 
     | 
    
         
            +
                    end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    def retry_stopped(event)
         
     | 
| 
      
 106 
     | 
    
         
            +
                      job = event.payload[:job]
         
     | 
| 
      
 107 
     | 
    
         
            +
                      ex = event.payload[:error]
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                      error do
         
     | 
| 
      
 110 
     | 
    
         
            +
                        "Stopped retrying #{job.class} due to a #{ex.class}, which reoccurred on #{job.executions} attempts."
         
     | 
| 
      
 111 
     | 
    
         
            +
                      end
         
     | 
| 
      
 112 
     | 
    
         
            +
                    end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                    def discard(event)
         
     | 
| 
      
 115 
     | 
    
         
            +
                      job = event.payload[:job]
         
     | 
| 
      
 116 
     | 
    
         
            +
                      ex = event.payload[:error]
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                      error do
         
     | 
| 
      
 119 
     | 
    
         
            +
                        "Discarded #{job.class} due to a #{ex.class}."
         
     | 
| 
      
 120 
     | 
    
         
            +
                      end
         
     | 
| 
      
 121 
     | 
    
         
            +
                    end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
       92 
123 
     | 
    
         
             
                    private
         
     | 
| 
       93 
124 
     | 
    
         
             
                      def queue_name(event)
         
     | 
| 
       94 
125 
     | 
    
         
             
                        event.payload[:adapter].class.name.demodulize.remove("Adapter") + "(#{event.payload[:job].queue_name})"
         
     | 
| 
         @@ -3,19 +3,19 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            module ActiveJob
         
     | 
| 
       4 
4 
     | 
    
         
             
              # == Active Job adapters
         
     | 
| 
       5 
5 
     | 
    
         
             
              #
         
     | 
| 
       6 
     | 
    
         
            -
              # Active Job has adapters for the following  
     | 
| 
      
 6 
     | 
    
         
            +
              # Active Job has adapters for the following queuing backends:
         
     | 
| 
       7 
7 
     | 
    
         
             
              #
         
     | 
| 
       8 
8 
     | 
    
         
             
              # * {Backburner}[https://github.com/nesquena/backburner]
         
     | 
| 
       9 
9 
     | 
    
         
             
              # * {Delayed Job}[https://github.com/collectiveidea/delayed_job]
         
     | 
| 
       10 
     | 
    
         
            -
              # * {Qu}[https://github.com/bkeepers/qu]
         
     | 
| 
       11 
10 
     | 
    
         
             
              # * {Que}[https://github.com/chanks/que]
         
     | 
| 
       12 
11 
     | 
    
         
             
              # * {queue_classic}[https://github.com/QueueClassic/queue_classic]
         
     | 
| 
       13 
12 
     | 
    
         
             
              # * {Resque}[https://github.com/resque/resque]
         
     | 
| 
       14 
     | 
    
         
            -
              # * {Sidekiq}[ 
     | 
| 
      
 13 
     | 
    
         
            +
              # * {Sidekiq}[https://sidekiq.org]
         
     | 
| 
       15 
14 
     | 
    
         
             
              # * {Sneakers}[https://github.com/jondot/sneakers]
         
     | 
| 
       16 
15 
     | 
    
         
             
              # * {Sucker Punch}[https://github.com/brandonhilkert/sucker_punch]
         
     | 
| 
       17 
     | 
    
         
            -
              # * {Active Job Async Job}[ 
     | 
| 
       18 
     | 
    
         
            -
              # * {Active Job Inline}[ 
     | 
| 
      
 16 
     | 
    
         
            +
              # * {Active Job Async Job}[https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/AsyncAdapter.html]
         
     | 
| 
      
 17 
     | 
    
         
            +
              # * {Active Job Inline}[https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/InlineAdapter.html]
         
     | 
| 
      
 18 
     | 
    
         
            +
              # * Please Note: We are not accepting pull requests for new adapters. See the {README}[link:files/activejob/README_md.html] for more details.
         
     | 
| 
       19 
19 
     | 
    
         
             
              #
         
     | 
| 
       20 
20 
     | 
    
         
             
              # === Backends Features
         
     | 
| 
       21 
21 
     | 
    
         
             
              #
         
     | 
| 
         @@ -23,7 +23,6 @@ module ActiveJob 
     | 
|
| 
       23 
23 
     | 
    
         
             
              #   |-------------------|-------|--------|------------|------------|---------|---------|
         
     | 
| 
       24 
24 
     | 
    
         
             
              #   | Backburner        | Yes   | Yes    | Yes        | Yes        | Job     | Global  |
         
     | 
| 
       25 
25 
     | 
    
         
             
              #   | Delayed Job       | Yes   | Yes    | Yes        | Job        | Global  | Global  |
         
     | 
| 
       26 
     | 
    
         
            -
              #   | Qu                | Yes   | Yes    | No         | No         | No      | Global  |
         
     | 
| 
       27 
26 
     | 
    
         
             
              #   | Que               | Yes   | Yes    | Yes        | Job        | No      | Job     |
         
     | 
| 
       28 
27 
     | 
    
         
             
              #   | queue_classic     | Yes   | Yes    | Yes*       | No         | No      | No      |
         
     | 
| 
       29 
28 
     | 
    
         
             
              #   | Resque            | Yes   | Yes    | Yes (Gem)  | Queue      | Global  | Yes     |
         
     | 
| 
         @@ -53,7 +52,7 @@ module ActiveJob 
     | 
|
| 
       53 
52 
     | 
    
         
             
              #
         
     | 
| 
       54 
53 
     | 
    
         
             
              # No: The adapter will run jobs at the next opportunity and cannot use perform_later.
         
     | 
| 
       55 
54 
     | 
    
         
             
              #
         
     | 
| 
       56 
     | 
    
         
            -
              # N/A: The adapter does not support  
     | 
| 
      
 55 
     | 
    
         
            +
              # N/A: The adapter does not support queuing.
         
     | 
| 
       57 
56 
     | 
    
         
             
              #
         
     | 
| 
       58 
57 
     | 
    
         
             
              # NOTE:
         
     | 
| 
       59 
58 
     | 
    
         
             
              # queue_classic supports job scheduling since version 3.1.
         
     | 
| 
         @@ -75,7 +74,7 @@ module ActiveJob 
     | 
|
| 
       75 
74 
     | 
    
         
             
              #
         
     | 
| 
       76 
75 
     | 
    
         
             
              # No: Does not allow the priority of jobs to be configured.
         
     | 
| 
       77 
76 
     | 
    
         
             
              #
         
     | 
| 
       78 
     | 
    
         
            -
              # N/A: The adapter does not support  
     | 
| 
      
 77 
     | 
    
         
            +
              # N/A: The adapter does not support queuing, and therefore sorting them.
         
     | 
| 
       79 
78 
     | 
    
         
             
              #
         
     | 
| 
       80 
79 
     | 
    
         
             
              # ==== Timeout
         
     | 
| 
       81 
80 
     | 
    
         
             
              #
         
     | 
| 
         @@ -114,7 +113,6 @@ module ActiveJob 
     | 
|
| 
       114 
113 
     | 
    
         
             
                autoload :InlineAdapter
         
     | 
| 
       115 
114 
     | 
    
         
             
                autoload :BackburnerAdapter
         
     | 
| 
       116 
115 
     | 
    
         
             
                autoload :DelayedJobAdapter
         
     | 
| 
       117 
     | 
    
         
            -
                autoload :QuAdapter
         
     | 
| 
       118 
116 
     | 
    
         
             
                autoload :QueAdapter
         
     | 
| 
       119 
117 
     | 
    
         
             
                autoload :QueueClassicAdapter
         
     | 
| 
       120 
118 
     | 
    
         
             
                autoload :ResqueAdapter
         
     | 
| 
         @@ -123,7 +121,7 @@ module ActiveJob 
     | 
|
| 
       123 
121 
     | 
    
         
             
                autoload :SuckerPunchAdapter
         
     | 
| 
       124 
122 
     | 
    
         
             
                autoload :TestAdapter
         
     | 
| 
       125 
123 
     | 
    
         | 
| 
       126 
     | 
    
         
            -
                ADAPTER = "Adapter" 
     | 
| 
      
 124 
     | 
    
         
            +
                ADAPTER = "Adapter"
         
     | 
| 
       127 
125 
     | 
    
         
             
                private_constant :ADAPTER
         
     | 
| 
       128 
126 
     | 
    
         | 
| 
       129 
127 
     | 
    
         
             
                class << self
         
     |