delayed_job 4.0.2 → 4.0.3
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 +5 -13
 - data/CHANGELOG.md +7 -0
 - data/README.md +12 -7
 - data/Rakefile +6 -1
 - data/delayed_job.gemspec +5 -5
 - data/lib/delayed/backend/base.rb +18 -20
 - data/lib/delayed/backend/shared_spec.rb +139 -138
 - data/lib/delayed/command.rb +75 -40
 - data/lib/delayed/exceptions.rb +2 -1
 - data/lib/delayed/lifecycle.rb +12 -11
 - data/lib/delayed/message_sending.rb +9 -10
 - data/lib/delayed/performable_mailer.rb +2 -2
 - data/lib/delayed/performable_method.rb +2 -2
 - data/lib/delayed/psych_ext.rb +29 -93
 - data/lib/delayed/recipes.rb +5 -5
 - data/lib/delayed/serialization/active_record.rb +11 -9
 - data/lib/delayed/syck_ext.rb +3 -3
 - data/lib/delayed/tasks.rb +5 -5
 - data/lib/delayed/worker.rb +42 -42
 - data/lib/generators/delayed_job/delayed_job_generator.rb +2 -3
 - data/spec/delayed/backend/test.rb +22 -17
 - data/spec/delayed/command_spec.rb +57 -0
 - data/spec/helper.rb +25 -12
 - data/spec/lifecycle_spec.rb +23 -15
 - data/spec/message_sending_spec.rb +34 -34
 - data/spec/performable_mailer_spec.rb +11 -11
 - data/spec/performable_method_spec.rb +24 -26
 - data/spec/psych_ext_spec.rb +12 -0
 - data/spec/sample_jobs.rb +46 -18
 - data/spec/test_backend_spec.rb +3 -3
 - data/spec/worker_spec.rb +27 -27
 - data/spec/yaml_ext_spec.rb +16 -16
 - metadata +12 -8
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,15 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
              data.tar.gz: !binary |-
         
     | 
| 
       6 
     | 
    
         
            -
                MDJmZDk3ZjJjYmNkZWFiMmIzNTU5MGQzMmNiOWM4Mzk2ODE0ODkzZg==
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: f8464e2a78c559301360d0c083d940e73f314406
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 819bd2dc775364ed9e6311be0a82fb3bdc20d6a6
         
     | 
| 
       7 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       8 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                ZWVkNjcxMWRlZmZmOTU4OGNiMTU0N2E2N2QwODczYmQyNjI5YmM3MDc3ZTNm
         
     | 
| 
       11 
     | 
    
         
            -
                YTI2Njk1NzBjZDFmYTkxZmE1YmVkYzJkOWI3NDZiODc2NDc1NjM=
         
     | 
| 
       12 
     | 
    
         
            -
              data.tar.gz: !binary |-
         
     | 
| 
       13 
     | 
    
         
            -
                OTBkOGMwYjNiZGIxNWMxODk3ZjI1OWFlZTU5NDlmNTZiZTBhNGQ0ZTY1ZjRm
         
     | 
| 
       14 
     | 
    
         
            -
                ZWYwYzFkZjgxMTE5OWJhMzg3NWU0YzU3MWNhMGJmMjg0N2Y4NDk5MjY5ZDE3
         
     | 
| 
       15 
     | 
    
         
            -
                NDMxYWFmOTU0M2FhZWJmMzIyYmNlMDZiYjJjODg0NjM0NWVkODQ=
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: c7d9b76c5f6244b37e79f2df7f5d5d270bd0769366ab0d93967ca02bd9ff434b98801ed92032815d0e0dd1abba5f9617881dd64aeabf09ed0700066f59985a3f
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 3f99c1bcddf3c835a4eea9cd200b559d1d284d169633016e79b0303549583be78cdfd888671139fe83ecec669b140171bb255d3f4bf03eaa9a4a45ed2c2bc7e2
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -1,3 +1,10 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            4.0.3 - 2014-09-04
         
     | 
| 
      
 2 
     | 
    
         
            +
            ==================
         
     | 
| 
      
 3 
     | 
    
         
            +
            * Added --pools option to delayed_job command
         
     | 
| 
      
 4 
     | 
    
         
            +
            * Removed a bunch of the Psych hacks
         
     | 
| 
      
 5 
     | 
    
         
            +
            * Improved deserialization error reporting
         
     | 
| 
      
 6 
     | 
    
         
            +
            * Misc bug fixes
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
       1 
8 
     | 
    
         
             
            4.0.2 - 2014-06-24
         
     | 
| 
       2 
9 
     | 
    
         
             
            ==================
         
     | 
| 
       3 
10 
     | 
    
         
             
            * Add support for RSpec 3
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -190,6 +190,11 @@ You can then do the following: 
     | 
|
| 
       190 
190 
     | 
    
         
             
                RAILS_ENV=production script/delayed_job --queue=tracking start
         
     | 
| 
       191 
191 
     | 
    
         
             
                RAILS_ENV=production script/delayed_job --queues=mailers,tasks start
         
     | 
| 
       192 
192 
     | 
    
         | 
| 
      
 193 
     | 
    
         
            +
                # Use the --pool option to specify a worker pool. You can use this option multiple times to start different numbers of workers for different queues.
         
     | 
| 
      
 194 
     | 
    
         
            +
                # The following command will start 1 worker for the tracking queue,
         
     | 
| 
      
 195 
     | 
    
         
            +
                # 2 workers for the mailers and tasks queues, and 2 workers for any jobs:
         
     | 
| 
      
 196 
     | 
    
         
            +
                RAILS_ENV=production script/delayed_job --pool=tracking --pool=mailers,tasks:2 --pool=*:2 start
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
       193 
198 
     | 
    
         
             
                # Runs all available jobs and then exits
         
     | 
| 
       194 
199 
     | 
    
         
             
                RAILS_ENV=production script/delayed_job start --exit-on-complete
         
     | 
| 
       195 
200 
     | 
    
         
             
                # or to run in the foreground
         
     | 
| 
         @@ -310,22 +315,22 @@ end 
     | 
|
| 
       310 
315 
     | 
    
         | 
| 
       311 
316 
     | 
    
         
             
            On failure, the job is scheduled again in 5 seconds + N ** 4, where N is the number of retries.
         
     | 
| 
       312 
317 
     | 
    
         | 
| 
       313 
     | 
    
         
            -
            The default Worker.max_attempts is 25. After this, the job either deleted (default), or left in the database with "failed_at" set.
         
     | 
| 
      
 318 
     | 
    
         
            +
            The default `Worker.max_attempts` is 25. After this, the job either deleted (default), or left in the database with "failed_at" set.
         
     | 
| 
       314 
319 
     | 
    
         
             
            With the default of 25 attempts, the last retry will be 20 days later, with the last interval being almost 100 hours.
         
     | 
| 
       315 
320 
     | 
    
         | 
| 
       316 
     | 
    
         
            -
            The default Worker.max_run_time is 4.hours. If your job takes longer than that, another computer could pick it up. It's up to you to
         
     | 
| 
      
 321 
     | 
    
         
            +
            The default `Worker.max_run_time` is 4.hours. If your job takes longer than that, another computer could pick it up. It's up to you to
         
     | 
| 
       317 
322 
     | 
    
         
             
            make sure your job doesn't exceed this time. You should set this to the longest time you think the job could take.
         
     | 
| 
       318 
323 
     | 
    
         | 
| 
       319 
324 
     | 
    
         
             
            By default, it will delete failed jobs (and it always deletes successful jobs). If you want to keep failed jobs, set
         
     | 
| 
       320 
     | 
    
         
            -
            Delayed::Worker.destroy_failed_jobs = false 
     | 
| 
      
 325 
     | 
    
         
            +
            `Delayed::Worker.destroy_failed_jobs = false`. The failed jobs will be marked with non-null failed_at.
         
     | 
| 
       321 
326 
     | 
    
         | 
| 
       322 
     | 
    
         
            -
            By default all jobs are scheduled with priority = 0 
     | 
| 
      
 327 
     | 
    
         
            +
            By default all jobs are scheduled with `priority = 0`, which is top priority. You can change this by setting `Delayed::Worker.default_priority` to something else. Lower numbers have higher priority.
         
     | 
| 
       323 
328 
     | 
    
         | 
| 
       324 
     | 
    
         
            -
            The default behavior is to read 5 jobs from the queue when finding an available job. You can configure this by setting Delayed::Worker.read_ahead 
     | 
| 
      
 329 
     | 
    
         
            +
            The default behavior is to read 5 jobs from the queue when finding an available job. You can configure this by setting `Delayed::Worker.read_ahead`.
         
     | 
| 
       325 
330 
     | 
    
         | 
| 
       326 
     | 
    
         
            -
            By default all jobs will be queued without a named queue. A default named queue can be specified by using Delayed::Worker.default_queue_name 
     | 
| 
      
 331 
     | 
    
         
            +
            By default all jobs will be queued without a named queue. A default named queue can be specified by using `Delayed::Worker.default_queue_name`.
         
     | 
| 
       327 
332 
     | 
    
         | 
| 
       328 
     | 
    
         
            -
            It is possible to disable delayed jobs for testing purposes. Set Delayed::Worker.delay_jobs = false to execute all jobs realtime.
         
     | 
| 
      
 333 
     | 
    
         
            +
            It is possible to disable delayed jobs for testing purposes. Set `Delayed::Worker.delay_jobs = false` to execute all jobs realtime.
         
     | 
| 
       329 
334 
     | 
    
         | 
| 
       330 
335 
     | 
    
         
             
            Here is an example of changing job parameters in Rails:
         
     | 
| 
       331 
336 
     | 
    
         | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/delayed_job.gemspec
    CHANGED
    
    | 
         @@ -1,9 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            Gem::Specification.new do |spec|
         
     | 
| 
       2 
     | 
    
         
            -
              spec.add_dependency 
     | 
| 
       3 
     | 
    
         
            -
              spec.authors        = [ 
     | 
| 
       4 
     | 
    
         
            -
              spec.description    =  
     | 
| 
      
 2 
     | 
    
         
            +
              spec.add_dependency 'activesupport', ['>= 3.0', '< 4.2']
         
     | 
| 
      
 3 
     | 
    
         
            +
              spec.authors        = ['Brandon Keepers', 'Brian Ryckbost', 'Chris Gaffney', 'David Genord II', 'Erik Michaels-Ober', 'Matt Griffin', 'Steve Richert', 'Tobias Lütke']
         
     | 
| 
      
 4 
     | 
    
         
            +
              spec.description    = 'Delayed_job (or DJ) encapsulates the common pattern of asynchronously executing longer tasks in the background. It is a direct extraction from Shopify where the job table is responsible for a multitude of core tasks.'
         
     | 
| 
       5 
5 
     | 
    
         
             
              spec.email          = ['brian@collectiveidea.com']
         
     | 
| 
       6 
     | 
    
         
            -
              spec.files          = %w 
     | 
| 
      
 6 
     | 
    
         
            +
              spec.files          = %w[CHANGELOG.md CONTRIBUTING.md LICENSE.md README.md Rakefile delayed_job.gemspec]
         
     | 
| 
       7 
7 
     | 
    
         
             
              spec.files         += Dir.glob('{contrib,lib,recipes,spec}/**/*')
         
     | 
| 
       8 
8 
     | 
    
         
             
              spec.homepage       = 'http://github.com/collectiveidea/delayed_job'
         
     | 
| 
       9 
9 
     | 
    
         
             
              spec.licenses       = ['MIT']
         
     | 
| 
         @@ -11,5 +11,5 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       11 
11 
     | 
    
         
             
              spec.require_paths  = ['lib']
         
     | 
| 
       12 
12 
     | 
    
         
             
              spec.summary        = 'Database-backed asynchronous priority queue system -- Extracted from Shopify'
         
     | 
| 
       13 
13 
     | 
    
         
             
              spec.test_files     = Dir.glob('spec/**/*')
         
     | 
| 
       14 
     | 
    
         
            -
              spec.version        = '4.0. 
     | 
| 
      
 14 
     | 
    
         
            +
              spec.version        = '4.0.3'
         
     | 
| 
       15 
15 
     | 
    
         
             
            end
         
     | 
    
        data/lib/delayed/backend/base.rb
    CHANGED
    
    | 
         @@ -16,7 +16,7 @@ module Delayed 
     | 
|
| 
       16 
16 
     | 
    
         
             
                      options[:payload_object] ||= args.shift
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
                      if args.size > 0
         
     | 
| 
       19 
     | 
    
         
            -
                        warn  
     | 
| 
      
 19 
     | 
    
         
            +
                        warn '[DEPRECATION] Passing multiple arguments to `#enqueue` is deprecated. Pass a hash with :priority and :run_at.'
         
     | 
| 
       20 
20 
     | 
    
         
             
                        options[:priority] = args.first || options[:priority]
         
     | 
| 
       21 
21 
     | 
    
         
             
                        options[:run_at]   = args[1]
         
     | 
| 
       22 
22 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -26,7 +26,7 @@ module Delayed 
     | 
|
| 
       26 
26 
     | 
    
         
             
                      end
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
28 
     | 
    
         
             
                      if Delayed::Worker.delay_jobs
         
     | 
| 
       29 
     | 
    
         
            -
                         
     | 
| 
      
 29 
     | 
    
         
            +
                        new(options).tap do |job|
         
     | 
| 
       30 
30 
     | 
    
         
             
                          Delayed::Worker.lifecycle.run_callbacks(:enqueue, job) do
         
     | 
| 
       31 
31 
     | 
    
         
             
                            job.hook(:enqueue)
         
     | 
| 
       32 
32 
     | 
    
         
             
                            job.save
         
     | 
| 
         @@ -48,7 +48,7 @@ module Delayed 
     | 
|
| 
       48 
48 
     | 
    
         
             
                    end
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
       50 
50 
     | 
    
         
             
                    # Allow the backend to attempt recovery from reserve errors
         
     | 
| 
       51 
     | 
    
         
            -
                    def recover_from( 
     | 
| 
      
 51 
     | 
    
         
            +
                    def recover_from(_error)
         
     | 
| 
       52 
52 
     | 
    
         
             
                    end
         
     | 
| 
       53 
53 
     | 
    
         | 
| 
       54 
54 
     | 
    
         
             
                    # Hook method that is called before a new worker is forked
         
     | 
| 
         @@ -60,7 +60,7 @@ module Delayed 
     | 
|
| 
       60 
60 
     | 
    
         
             
                    end
         
     | 
| 
       61 
61 
     | 
    
         | 
| 
       62 
62 
     | 
    
         
             
                    def work_off(num = 100)
         
     | 
| 
       63 
     | 
    
         
            -
                      warn  
     | 
| 
      
 63 
     | 
    
         
            +
                      warn '[DEPRECATION] `Delayed::Job.work_off` is deprecated. Use `Delayed::Worker.new.work_off instead.'
         
     | 
| 
       64 
64 
     | 
    
         
             
                      Delayed::Worker.new.work_off(num)
         
     | 
| 
       65 
65 
     | 
    
         
             
                    end
         
     | 
| 
       66 
66 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -70,12 +70,10 @@ module Delayed 
     | 
|
| 
       70 
70 
     | 
    
         
             
                  end
         
     | 
| 
       71 
71 
     | 
    
         
             
                  alias_method :failed, :failed?
         
     | 
| 
       72 
72 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
                  ParseObjectFromYaml = /\!ruby\/\w+\:([^\s]+)/
         
     | 
| 
      
 73 
     | 
    
         
            +
                  ParseObjectFromYaml = /\!ruby\/\w+\:([^\s]+)/ # rubocop:disable ConstantName
         
     | 
| 
       74 
74 
     | 
    
         | 
| 
       75 
75 
     | 
    
         
             
                  def name
         
     | 
| 
       76 
     | 
    
         
            -
                    @name ||= payload_object.respond_to?(:display_name) ?
         
     | 
| 
       77 
     | 
    
         
            -
                                payload_object.display_name :
         
     | 
| 
       78 
     | 
    
         
            -
                                payload_object.class.name
         
     | 
| 
      
 76 
     | 
    
         
            +
                    @name ||= payload_object.respond_to?(:display_name) ? payload_object.display_name : payload_object.class.name
         
     | 
| 
       79 
77 
     | 
    
         
             
                  rescue DeserializationError
         
     | 
| 
       80 
78 
     | 
    
         
             
                    ParseObjectFromYaml.match(handler)[1]
         
     | 
| 
       81 
79 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -87,15 +85,14 @@ module Delayed 
     | 
|
| 
       87 
85 
     | 
    
         | 
| 
       88 
86 
     | 
    
         
             
                  def payload_object
         
     | 
| 
       89 
87 
     | 
    
         
             
                    if YAML.respond_to?(:unsafe_load)
         
     | 
| 
       90 
     | 
    
         
            -
                      #See https://github.com/dtao/safe_yaml
         
     | 
| 
       91 
     | 
    
         
            -
                      #When the method is there, we need to load our YAML like this...
         
     | 
| 
       92 
     | 
    
         
            -
                      @payload_object ||= YAML.load( 
     | 
| 
      
 88 
     | 
    
         
            +
                      # See https://github.com/dtao/safe_yaml
         
     | 
| 
      
 89 
     | 
    
         
            +
                      # When the method is there, we need to load our YAML like this...
         
     | 
| 
      
 90 
     | 
    
         
            +
                      @payload_object ||= YAML.load(handler, :safe => false)
         
     | 
| 
       93 
91 
     | 
    
         
             
                    else
         
     | 
| 
       94 
     | 
    
         
            -
                      @payload_object ||= YAML.load( 
     | 
| 
      
 92 
     | 
    
         
            +
                      @payload_object ||= YAML.load(handler)
         
     | 
| 
       95 
93 
     | 
    
         
             
                    end
         
     | 
| 
       96 
94 
     | 
    
         
             
                  rescue TypeError, LoadError, NameError, ArgumentError => e
         
     | 
| 
       97 
     | 
    
         
            -
                    raise DeserializationError,
         
     | 
| 
       98 
     | 
    
         
            -
                      "Job failed to load: #{e.message}. Handler: #{handler.inspect}"
         
     | 
| 
      
 95 
     | 
    
         
            +
                    raise DeserializationError, "Job failed to load: #{e.message}. Handler: #{handler.inspect}"
         
     | 
| 
       99 
96 
     | 
    
         
             
                  end
         
     | 
| 
       100 
97 
     | 
    
         | 
| 
       101 
98 
     | 
    
         
             
                  def invoke_job
         
     | 
| 
         @@ -104,7 +101,7 @@ module Delayed 
     | 
|
| 
       104 
101 
     | 
    
         
             
                        hook :before
         
     | 
| 
       105 
102 
     | 
    
         
             
                        payload_object.perform
         
     | 
| 
       106 
103 
     | 
    
         
             
                        hook :success
         
     | 
| 
       107 
     | 
    
         
            -
                      rescue  
     | 
| 
      
 104 
     | 
    
         
            +
                      rescue => e
         
     | 
| 
       108 
105 
     | 
    
         
             
                        hook :error, e
         
     | 
| 
       109 
106 
     | 
    
         
             
                        raise e
         
     | 
| 
       110 
107 
     | 
    
         
             
                      ensure
         
     | 
| 
         @@ -124,14 +121,15 @@ module Delayed 
     | 
|
| 
       124 
121 
     | 
    
         
             
                      method = payload_object.method(name)
         
     | 
| 
       125 
122 
     | 
    
         
             
                      method.arity == 0 ? method.call : method.call(self, *args)
         
     | 
| 
       126 
123 
     | 
    
         
             
                    end
         
     | 
| 
       127 
     | 
    
         
            -
                  rescue DeserializationError
         
     | 
| 
       128 
     | 
    
         
            -
                    # do nothing
         
     | 
| 
      
 124 
     | 
    
         
            +
                  rescue DeserializationError # rubocop:disable HandleExceptions
         
     | 
| 
       129 
125 
     | 
    
         
             
                  end
         
     | 
| 
       130 
126 
     | 
    
         | 
| 
       131 
127 
     | 
    
         
             
                  def reschedule_at
         
     | 
| 
       132 
     | 
    
         
            -
                    payload_object.respond_to?(:reschedule_at) 
     | 
| 
       133 
     | 
    
         
            -
                      payload_object.reschedule_at(self.class.db_time_now, attempts) 
     | 
| 
       134 
     | 
    
         
            -
             
     | 
| 
      
 128 
     | 
    
         
            +
                    if payload_object.respond_to?(:reschedule_at)
         
     | 
| 
      
 129 
     | 
    
         
            +
                      payload_object.reschedule_at(self.class.db_time_now, attempts)
         
     | 
| 
      
 130 
     | 
    
         
            +
                    else
         
     | 
| 
      
 131 
     | 
    
         
            +
                      self.class.db_time_now + (attempts**4) + 5
         
     | 
| 
      
 132 
     | 
    
         
            +
                    end
         
     | 
| 
       135 
133 
     | 
    
         
             
                  end
         
     | 
| 
       136 
134 
     | 
    
         | 
| 
       137 
135 
     | 
    
         
             
                  def max_attempts
         
     | 
| 
         @@ -2,7 +2,7 @@ require File.expand_path('../../../../spec/sample_jobs', __FILE__) 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'active_support/core_ext'
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
            shared_examples_for  
     | 
| 
      
 5 
     | 
    
         
            +
            shared_examples_for 'a delayed_job backend' do
         
     | 
| 
       6 
6 
     | 
    
         
             
              let(:worker) { Delayed::Worker.new }
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
              def create_job(opts = {})
         
     | 
| 
         @@ -22,74 +22,74 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       22 
22 
     | 
    
         
             
                Delayed::Worker.reset
         
     | 
| 
       23 
23 
     | 
    
         
             
              end
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
              it  
     | 
| 
       26 
     | 
    
         
            -
                expect(described_class.create(:payload_object => ErrorJob.new 
     | 
| 
      
 25 
     | 
    
         
            +
              it 'sets run_at automatically if not set' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                expect(described_class.create(:payload_object => ErrorJob.new).run_at).not_to be_nil
         
     | 
| 
       27 
27 
     | 
    
         
             
              end
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
              it  
     | 
| 
      
 29 
     | 
    
         
            +
              it 'does not set run_at automatically if already set' do
         
     | 
| 
       30 
30 
     | 
    
         
             
                later = described_class.db_time_now + 5.minutes
         
     | 
| 
       31 
31 
     | 
    
         
             
                job = described_class.create(:payload_object => ErrorJob.new, :run_at => later)
         
     | 
| 
       32 
32 
     | 
    
         
             
                expect(job.run_at).to be_within(1).of(later)
         
     | 
| 
       33 
33 
     | 
    
         
             
              end
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
              describe  
     | 
| 
       36 
     | 
    
         
            -
                it  
     | 
| 
      
 35 
     | 
    
         
            +
              describe '#reload' do
         
     | 
| 
      
 36 
     | 
    
         
            +
                it 'reloads the payload' do
         
     | 
| 
       37 
37 
     | 
    
         
             
                  job = described_class.enqueue :payload_object => SimpleJob.new
         
     | 
| 
       38 
38 
     | 
    
         
             
                  expect(job.payload_object.object_id).not_to eq(job.reload.payload_object.object_id)
         
     | 
| 
       39 
39 
     | 
    
         
             
                end
         
     | 
| 
       40 
40 
     | 
    
         
             
              end
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
              describe  
     | 
| 
       43 
     | 
    
         
            -
                context  
     | 
| 
      
 42 
     | 
    
         
            +
              describe 'enqueue' do
         
     | 
| 
      
 43 
     | 
    
         
            +
                context 'with a hash' do
         
     | 
| 
       44 
44 
     | 
    
         
             
                  it "raises ArgumentError when handler doesn't respond_to :perform" do
         
     | 
| 
       45 
     | 
    
         
            -
                    expect{described_class.enqueue(:payload_object => Object.new)}.to raise_error(ArgumentError)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    expect { described_class.enqueue(:payload_object => Object.new) }.to raise_error(ArgumentError)
         
     | 
| 
       46 
46 
     | 
    
         
             
                  end
         
     | 
| 
       47 
47 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
                  it  
     | 
| 
      
 48 
     | 
    
         
            +
                  it 'is able to set priority' do
         
     | 
| 
       49 
49 
     | 
    
         
             
                    job = described_class.enqueue :payload_object => SimpleJob.new, :priority => 5
         
     | 
| 
       50 
50 
     | 
    
         
             
                    expect(job.priority).to eq(5)
         
     | 
| 
       51 
51 
     | 
    
         
             
                  end
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
                  it  
     | 
| 
      
 53 
     | 
    
         
            +
                  it 'uses default priority' do
         
     | 
| 
       54 
54 
     | 
    
         
             
                    job = described_class.enqueue :payload_object => SimpleJob.new
         
     | 
| 
       55 
55 
     | 
    
         
             
                    expect(job.priority).to eq(99)
         
     | 
| 
       56 
56 
     | 
    
         
             
                  end
         
     | 
| 
       57 
57 
     | 
    
         | 
| 
       58 
     | 
    
         
            -
                  it  
     | 
| 
      
 58 
     | 
    
         
            +
                  it 'is able to set run_at' do
         
     | 
| 
       59 
59 
     | 
    
         
             
                    later = described_class.db_time_now + 5.minutes
         
     | 
| 
       60 
60 
     | 
    
         
             
                    job = described_class.enqueue :payload_object => SimpleJob.new, :run_at => later
         
     | 
| 
       61 
61 
     | 
    
         
             
                    expect(job.run_at).to be_within(1).of(later)
         
     | 
| 
       62 
62 
     | 
    
         
             
                  end
         
     | 
| 
       63 
63 
     | 
    
         | 
| 
       64 
     | 
    
         
            -
                  it  
     | 
| 
      
 64 
     | 
    
         
            +
                  it 'is able to set queue' do
         
     | 
| 
       65 
65 
     | 
    
         
             
                    job = described_class.enqueue :payload_object => SimpleJob.new, :queue => 'tracking'
         
     | 
| 
       66 
66 
     | 
    
         
             
                    expect(job.queue).to eq('tracking')
         
     | 
| 
       67 
67 
     | 
    
         
             
                  end
         
     | 
| 
       68 
68 
     | 
    
         
             
                end
         
     | 
| 
       69 
69 
     | 
    
         | 
| 
       70 
     | 
    
         
            -
                context  
     | 
| 
      
 70 
     | 
    
         
            +
                context 'with multiple arguments' do
         
     | 
| 
       71 
71 
     | 
    
         
             
                  it "raises ArgumentError when handler doesn't respond_to :perform" do
         
     | 
| 
       72 
     | 
    
         
            -
                    expect{described_class.enqueue(Object.new)}.to raise_error(ArgumentError)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    expect { described_class.enqueue(Object.new) }.to raise_error(ArgumentError)
         
     | 
| 
       73 
73 
     | 
    
         
             
                  end
         
     | 
| 
       74 
74 
     | 
    
         | 
| 
       75 
     | 
    
         
            -
                  it  
     | 
| 
      
 75 
     | 
    
         
            +
                  it 'increases count after enqueuing items' do
         
     | 
| 
       76 
76 
     | 
    
         
             
                    described_class.enqueue SimpleJob.new
         
     | 
| 
       77 
77 
     | 
    
         
             
                    expect(described_class.count).to eq(1)
         
     | 
| 
       78 
78 
     | 
    
         
             
                  end
         
     | 
| 
       79 
79 
     | 
    
         | 
| 
       80 
     | 
    
         
            -
                  it  
     | 
| 
      
 80 
     | 
    
         
            +
                  it 'is able to set priority [DEPRECATED]' do
         
     | 
| 
       81 
81 
     | 
    
         
             
                    silence_warnings do
         
     | 
| 
       82 
82 
     | 
    
         
             
                      job = described_class.enqueue SimpleJob.new, 5
         
     | 
| 
       83 
83 
     | 
    
         
             
                      expect(job.priority).to eq(5)
         
     | 
| 
       84 
84 
     | 
    
         
             
                    end
         
     | 
| 
       85 
85 
     | 
    
         
             
                  end
         
     | 
| 
       86 
86 
     | 
    
         | 
| 
       87 
     | 
    
         
            -
                  it  
     | 
| 
      
 87 
     | 
    
         
            +
                  it 'uses default priority when it is not set' do
         
     | 
| 
       88 
88 
     | 
    
         
             
                    @job = described_class.enqueue SimpleJob.new
         
     | 
| 
       89 
89 
     | 
    
         
             
                    expect(@job.priority).to eq(99)
         
     | 
| 
       90 
90 
     | 
    
         
             
                  end
         
     | 
| 
       91 
91 
     | 
    
         | 
| 
       92 
     | 
    
         
            -
                  it  
     | 
| 
      
 92 
     | 
    
         
            +
                  it 'is able to set run_at [DEPRECATED]' do
         
     | 
| 
       93 
93 
     | 
    
         
             
                    silence_warnings do
         
     | 
| 
       94 
94 
     | 
    
         
             
                      later = described_class.db_time_now + 5.minutes
         
     | 
| 
       95 
95 
     | 
    
         
             
                      @job = described_class.enqueue SimpleJob.new, 5, later
         
     | 
| 
         @@ -97,41 +97,41 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       97 
97 
     | 
    
         
             
                    end
         
     | 
| 
       98 
98 
     | 
    
         
             
                  end
         
     | 
| 
       99 
99 
     | 
    
         | 
| 
       100 
     | 
    
         
            -
                  it  
     | 
| 
      
 100 
     | 
    
         
            +
                  it 'works with jobs in modules' do
         
     | 
| 
       101 
101 
     | 
    
         
             
                    M::ModuleJob.runs = 0
         
     | 
| 
       102 
102 
     | 
    
         
             
                    job = described_class.enqueue M::ModuleJob.new
         
     | 
| 
       103 
     | 
    
         
            -
                    expect{job.invoke_job}.to change { M::ModuleJob.runs }.from(0).to(1)
         
     | 
| 
      
 103 
     | 
    
         
            +
                    expect { job.invoke_job }.to change { M::ModuleJob.runs }.from(0).to(1)
         
     | 
| 
       104 
104 
     | 
    
         
             
                  end
         
     | 
| 
       105 
105 
     | 
    
         
             
                end
         
     | 
| 
       106 
106 
     | 
    
         | 
| 
       107 
     | 
    
         
            -
                context  
     | 
| 
      
 107 
     | 
    
         
            +
                context 'with delay_jobs = false' do
         
     | 
| 
       108 
108 
     | 
    
         
             
                  before(:each) do
         
     | 
| 
       109 
109 
     | 
    
         
             
                    Delayed::Worker.delay_jobs = false
         
     | 
| 
       110 
110 
     | 
    
         
             
                  end
         
     | 
| 
       111 
111 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
                  it  
     | 
| 
      
 112 
     | 
    
         
            +
                  it 'does not increase count after enqueuing items' do
         
     | 
| 
       113 
113 
     | 
    
         
             
                    described_class.enqueue SimpleJob.new
         
     | 
| 
       114 
114 
     | 
    
         
             
                    expect(described_class.count).to eq(0)
         
     | 
| 
       115 
115 
     | 
    
         
             
                  end
         
     | 
| 
       116 
116 
     | 
    
         | 
| 
       117 
     | 
    
         
            -
                  it  
     | 
| 
      
 117 
     | 
    
         
            +
                  it 'invokes the enqueued job' do
         
     | 
| 
       118 
118 
     | 
    
         
             
                    job = SimpleJob.new
         
     | 
| 
       119 
119 
     | 
    
         
             
                    expect(job).to receive(:perform)
         
     | 
| 
       120 
120 
     | 
    
         
             
                    described_class.enqueue job
         
     | 
| 
       121 
121 
     | 
    
         
             
                  end
         
     | 
| 
       122 
122 
     | 
    
         | 
| 
       123 
     | 
    
         
            -
                  it  
     | 
| 
      
 123 
     | 
    
         
            +
                  it 'returns a job, not the result of invocation' do
         
     | 
| 
       124 
124 
     | 
    
         
             
                    expect(described_class.enqueue(SimpleJob.new)).to be_instance_of(described_class)
         
     | 
| 
       125 
125 
     | 
    
         
             
                  end
         
     | 
| 
       126 
126 
     | 
    
         
             
                end
         
     | 
| 
       127 
127 
     | 
    
         
             
              end
         
     | 
| 
       128 
128 
     | 
    
         | 
| 
       129 
     | 
    
         
            -
              describe  
     | 
| 
      
 129 
     | 
    
         
            +
              describe 'callbacks' do
         
     | 
| 
       130 
130 
     | 
    
         
             
                before(:each) do
         
     | 
| 
       131 
131 
     | 
    
         
             
                  CallbackJob.messages = []
         
     | 
| 
       132 
132 
     | 
    
         
             
                end
         
     | 
| 
       133 
133 
     | 
    
         | 
| 
       134 
     | 
    
         
            -
                %w 
     | 
| 
      
 134 
     | 
    
         
            +
                %w[before success after].each do |callback|
         
     | 
| 
       135 
135 
     | 
    
         
             
                  it "calls #{callback} with job" do
         
     | 
| 
       136 
136 
     | 
    
         
             
                    job = described_class.enqueue(CallbackJob.new)
         
     | 
| 
       137 
137 
     | 
    
         
             
                    expect(job.payload_object).to receive(callback).with(job)
         
     | 
| 
         @@ -139,48 +139,48 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       139 
139 
     | 
    
         
             
                  end
         
     | 
| 
       140 
140 
     | 
    
         
             
                end
         
     | 
| 
       141 
141 
     | 
    
         | 
| 
       142 
     | 
    
         
            -
                it  
     | 
| 
      
 142 
     | 
    
         
            +
                it 'calls before and after callbacks' do
         
     | 
| 
       143 
143 
     | 
    
         
             
                  job = described_class.enqueue(CallbackJob.new)
         
     | 
| 
       144 
     | 
    
         
            -
                  expect(CallbackJob.messages).to eq([ 
     | 
| 
      
 144 
     | 
    
         
            +
                  expect(CallbackJob.messages).to eq(['enqueue'])
         
     | 
| 
       145 
145 
     | 
    
         
             
                  job.invoke_job
         
     | 
| 
       146 
     | 
    
         
            -
                  expect(CallbackJob.messages).to eq([ 
     | 
| 
      
 146 
     | 
    
         
            +
                  expect(CallbackJob.messages).to eq(%w[enqueue before perform success after])
         
     | 
| 
       147 
147 
     | 
    
         
             
                end
         
     | 
| 
       148 
148 
     | 
    
         | 
| 
       149 
     | 
    
         
            -
                it  
     | 
| 
      
 149 
     | 
    
         
            +
                it 'calls the after callback with an error' do
         
     | 
| 
       150 
150 
     | 
    
         
             
                  job = described_class.enqueue(CallbackJob.new)
         
     | 
| 
       151 
     | 
    
         
            -
                  expect(job.payload_object).to receive(:perform).and_raise(RuntimeError.new( 
     | 
| 
      
 151 
     | 
    
         
            +
                  expect(job.payload_object).to receive(:perform).and_raise(RuntimeError.new('fail'))
         
     | 
| 
       152 
152 
     | 
    
         | 
| 
       153 
     | 
    
         
            -
                  expect{job.invoke_job}.to raise_error
         
     | 
| 
       154 
     | 
    
         
            -
                  expect(CallbackJob.messages).to eq([ 
     | 
| 
      
 153 
     | 
    
         
            +
                  expect { job.invoke_job }.to raise_error
         
     | 
| 
      
 154 
     | 
    
         
            +
                  expect(CallbackJob.messages).to eq(['enqueue', 'before', 'error: RuntimeError', 'after'])
         
     | 
| 
       155 
155 
     | 
    
         
             
                end
         
     | 
| 
       156 
156 
     | 
    
         | 
| 
       157 
     | 
    
         
            -
                it  
     | 
| 
      
 157 
     | 
    
         
            +
                it 'calls error when before raises an error' do
         
     | 
| 
       158 
158 
     | 
    
         
             
                  job = described_class.enqueue(CallbackJob.new)
         
     | 
| 
       159 
     | 
    
         
            -
                  expect(job.payload_object).to receive(:before).and_raise(RuntimeError.new( 
     | 
| 
       160 
     | 
    
         
            -
                  expect{job.invoke_job}.to raise_error(RuntimeError)
         
     | 
| 
       161 
     | 
    
         
            -
                  expect(CallbackJob.messages).to eq([ 
     | 
| 
      
 159 
     | 
    
         
            +
                  expect(job.payload_object).to receive(:before).and_raise(RuntimeError.new('fail'))
         
     | 
| 
      
 160 
     | 
    
         
            +
                  expect { job.invoke_job }.to raise_error(RuntimeError)
         
     | 
| 
      
 161 
     | 
    
         
            +
                  expect(CallbackJob.messages).to eq(['enqueue', 'error: RuntimeError', 'after'])
         
     | 
| 
       162 
162 
     | 
    
         
             
                end
         
     | 
| 
       163 
163 
     | 
    
         
             
              end
         
     | 
| 
       164 
164 
     | 
    
         | 
| 
       165 
     | 
    
         
            -
              describe  
     | 
| 
       166 
     | 
    
         
            -
                it  
     | 
| 
       167 
     | 
    
         
            -
                  job = described_class.new :handler =>  
     | 
| 
       168 
     | 
    
         
            -
                  expect{job.payload_object}.to raise_error(Delayed::DeserializationError)
         
     | 
| 
      
 165 
     | 
    
         
            +
              describe 'payload_object' do
         
     | 
| 
      
 166 
     | 
    
         
            +
                it 'raises a DeserializationError when the job class is totally unknown' do
         
     | 
| 
      
 167 
     | 
    
         
            +
                  job = described_class.new :handler => '--- !ruby/object:JobThatDoesNotExist {}'
         
     | 
| 
      
 168 
     | 
    
         
            +
                  expect { job.payload_object }.to raise_error(Delayed::DeserializationError)
         
     | 
| 
       169 
169 
     | 
    
         
             
                end
         
     | 
| 
       170 
170 
     | 
    
         | 
| 
       171 
     | 
    
         
            -
                it  
     | 
| 
       172 
     | 
    
         
            -
                  job = described_class.new :handler =>  
     | 
| 
       173 
     | 
    
         
            -
                  expect{job.payload_object}.to raise_error(Delayed::DeserializationError)
         
     | 
| 
      
 171 
     | 
    
         
            +
                it 'raises a DeserializationError when the job struct is totally unknown' do
         
     | 
| 
      
 172 
     | 
    
         
            +
                  job = described_class.new :handler => '--- !ruby/struct:StructThatDoesNotExist {}'
         
     | 
| 
      
 173 
     | 
    
         
            +
                  expect { job.payload_object }.to raise_error(Delayed::DeserializationError)
         
     | 
| 
       174 
174 
     | 
    
         
             
                end
         
     | 
| 
       175 
175 
     | 
    
         | 
| 
       176 
     | 
    
         
            -
                it  
     | 
| 
       177 
     | 
    
         
            -
                  job = described_class.new :handler =>  
     | 
| 
      
 176 
     | 
    
         
            +
                it 'raises a DeserializationError when the YAML.load raises argument error' do
         
     | 
| 
      
 177 
     | 
    
         
            +
                  job = described_class.new :handler => '--- !ruby/struct:GoingToRaiseArgError {}'
         
     | 
| 
       178 
178 
     | 
    
         
             
                  expect(YAML).to receive(:load).and_raise(ArgumentError)
         
     | 
| 
       179 
     | 
    
         
            -
                  expect{job.payload_object}.to raise_error(Delayed::DeserializationError)
         
     | 
| 
      
 179 
     | 
    
         
            +
                  expect { job.payload_object }.to raise_error(Delayed::DeserializationError)
         
     | 
| 
       180 
180 
     | 
    
         
             
                end
         
     | 
| 
       181 
181 
     | 
    
         
             
              end
         
     | 
| 
       182 
182 
     | 
    
         | 
| 
       183 
     | 
    
         
            -
              describe  
     | 
| 
      
 183 
     | 
    
         
            +
              describe 'reserve' do
         
     | 
| 
       184 
184 
     | 
    
         
             
                before do
         
     | 
| 
       185 
185 
     | 
    
         
             
                  Delayed::Worker.max_run_time = 2.minutes
         
     | 
| 
       186 
186 
     | 
    
         
             
                end
         
     | 
| 
         @@ -189,28 +189,28 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       189 
189 
     | 
    
         
             
                  Time.zone = nil
         
     | 
| 
       190 
190 
     | 
    
         
             
                end
         
     | 
| 
       191 
191 
     | 
    
         | 
| 
       192 
     | 
    
         
            -
                it  
     | 
| 
      
 192 
     | 
    
         
            +
                it 'does not reserve failed jobs' do
         
     | 
| 
       193 
193 
     | 
    
         
             
                  create_job :attempts => 50, :failed_at => described_class.db_time_now
         
     | 
| 
       194 
194 
     | 
    
         
             
                  expect(described_class.reserve(worker)).to be_nil
         
     | 
| 
       195 
195 
     | 
    
         
             
                end
         
     | 
| 
       196 
196 
     | 
    
         | 
| 
       197 
     | 
    
         
            -
                it  
     | 
| 
      
 197 
     | 
    
         
            +
                it 'does not reserve jobs scheduled for the future' do
         
     | 
| 
       198 
198 
     | 
    
         
             
                  create_job :run_at => described_class.db_time_now + 1.minute
         
     | 
| 
       199 
199 
     | 
    
         
             
                  expect(described_class.reserve(worker)).to be_nil
         
     | 
| 
       200 
200 
     | 
    
         
             
                end
         
     | 
| 
       201 
201 
     | 
    
         | 
| 
       202 
     | 
    
         
            -
                it  
     | 
| 
      
 202 
     | 
    
         
            +
                it 'reserves jobs scheduled for the past' do
         
     | 
| 
       203 
203 
     | 
    
         
             
                  job = create_job :run_at => described_class.db_time_now - 1.minute
         
     | 
| 
       204 
204 
     | 
    
         
             
                  expect(described_class.reserve(worker)).to eq(job)
         
     | 
| 
       205 
205 
     | 
    
         
             
                end
         
     | 
| 
       206 
206 
     | 
    
         | 
| 
       207 
     | 
    
         
            -
                it  
     | 
| 
      
 207 
     | 
    
         
            +
                it 'reserves jobs scheduled for the past when time zones are involved' do
         
     | 
| 
       208 
208 
     | 
    
         
             
                  Time.zone = 'US/Eastern'
         
     | 
| 
       209 
209 
     | 
    
         
             
                  job = create_job :run_at => described_class.db_time_now - 1.minute
         
     | 
| 
       210 
210 
     | 
    
         
             
                  expect(described_class.reserve(worker)).to eq(job)
         
     | 
| 
       211 
211 
     | 
    
         
             
                end
         
     | 
| 
       212 
212 
     | 
    
         | 
| 
       213 
     | 
    
         
            -
                it  
     | 
| 
      
 213 
     | 
    
         
            +
                it 'does not reserve jobs locked by other workers' do
         
     | 
| 
       214 
214 
     | 
    
         
             
                  job = create_job
         
     | 
| 
       215 
215 
     | 
    
         
             
                  other_worker = Delayed::Worker.new
         
     | 
| 
       216 
216 
     | 
    
         
             
                  other_worker.name = 'other_worker'
         
     | 
| 
         @@ -218,51 +218,51 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       218 
218 
     | 
    
         
             
                  expect(described_class.reserve(worker)).to be_nil
         
     | 
| 
       219 
219 
     | 
    
         
             
                end
         
     | 
| 
       220 
220 
     | 
    
         | 
| 
       221 
     | 
    
         
            -
                it  
     | 
| 
      
 221 
     | 
    
         
            +
                it 'reserves open jobs' do
         
     | 
| 
       222 
222 
     | 
    
         
             
                  job = create_job
         
     | 
| 
       223 
223 
     | 
    
         
             
                  expect(described_class.reserve(worker)).to eq(job)
         
     | 
| 
       224 
224 
     | 
    
         
             
                end
         
     | 
| 
       225 
225 
     | 
    
         | 
| 
       226 
     | 
    
         
            -
                it  
     | 
| 
      
 226 
     | 
    
         
            +
                it 'reserves expired jobs' do
         
     | 
| 
       227 
227 
     | 
    
         
             
                  job = create_job(:locked_by => 'some other worker', :locked_at => described_class.db_time_now - Delayed::Worker.max_run_time - 1.minute)
         
     | 
| 
       228 
228 
     | 
    
         
             
                  expect(described_class.reserve(worker)).to eq(job)
         
     | 
| 
       229 
229 
     | 
    
         
             
                end
         
     | 
| 
       230 
230 
     | 
    
         | 
| 
       231 
     | 
    
         
            -
                it  
     | 
| 
      
 231 
     | 
    
         
            +
                it 'reserves own jobs' do
         
     | 
| 
       232 
232 
     | 
    
         
             
                  job = create_job(:locked_by => worker.name, :locked_at => (described_class.db_time_now - 1.minutes))
         
     | 
| 
       233 
233 
     | 
    
         
             
                  expect(described_class.reserve(worker)).to eq(job)
         
     | 
| 
       234 
234 
     | 
    
         
             
                end
         
     | 
| 
       235 
235 
     | 
    
         
             
              end
         
     | 
| 
       236 
236 
     | 
    
         | 
| 
       237 
     | 
    
         
            -
              context  
     | 
| 
       238 
     | 
    
         
            -
                it  
     | 
| 
       239 
     | 
    
         
            -
                  expect(described_class.create(:payload_object => ErrorJob.new 
     | 
| 
      
 237 
     | 
    
         
            +
              context '#name' do
         
     | 
| 
      
 238 
     | 
    
         
            +
                it 'is the class name of the job that was enqueued' do
         
     | 
| 
      
 239 
     | 
    
         
            +
                  expect(described_class.create(:payload_object => ErrorJob.new).name).to eq('ErrorJob')
         
     | 
| 
       240 
240 
     | 
    
         
             
                end
         
     | 
| 
       241 
241 
     | 
    
         | 
| 
       242 
     | 
    
         
            -
                it  
     | 
| 
      
 242 
     | 
    
         
            +
                it 'is the method that will be called if its a performable method object' do
         
     | 
| 
       243 
243 
     | 
    
         
             
                  job = described_class.new(:payload_object => NamedJob.new)
         
     | 
| 
       244 
244 
     | 
    
         
             
                  expect(job.name).to eq('named_job')
         
     | 
| 
       245 
245 
     | 
    
         
             
                end
         
     | 
| 
       246 
246 
     | 
    
         | 
| 
       247 
     | 
    
         
            -
                it  
     | 
| 
       248 
     | 
    
         
            -
                  job = Story.create(:text =>  
     | 
| 
      
 247 
     | 
    
         
            +
                it 'is the instance method that will be called if its a performable method object' do
         
     | 
| 
      
 248 
     | 
    
         
            +
                  job = Story.create(:text => '...').delay.save
         
     | 
| 
       249 
249 
     | 
    
         
             
                  expect(job.name).to eq('Story#save')
         
     | 
| 
       250 
250 
     | 
    
         
             
                end
         
     | 
| 
       251 
251 
     | 
    
         | 
| 
       252 
     | 
    
         
            -
                it  
     | 
| 
       253 
     | 
    
         
            -
                  job = Story.create(:text =>  
     | 
| 
      
 252 
     | 
    
         
            +
                it 'parses from handler on deserialization error' do
         
     | 
| 
      
 253 
     | 
    
         
            +
                  job = Story.create(:text => '...').delay.text
         
     | 
| 
       254 
254 
     | 
    
         
             
                  job.payload_object.object.destroy
         
     | 
| 
       255 
255 
     | 
    
         
             
                  expect(job.reload.name).to eq('Delayed::PerformableMethod')
         
     | 
| 
       256 
256 
     | 
    
         
             
                end
         
     | 
| 
       257 
257 
     | 
    
         
             
              end
         
     | 
| 
       258 
258 
     | 
    
         | 
| 
       259 
     | 
    
         
            -
              context  
     | 
| 
      
 259 
     | 
    
         
            +
              context 'worker prioritization' do
         
     | 
| 
       260 
260 
     | 
    
         
             
                after do
         
     | 
| 
       261 
261 
     | 
    
         
             
                  Delayed::Worker.max_priority = nil
         
     | 
| 
       262 
262 
     | 
    
         
             
                  Delayed::Worker.min_priority = nil
         
     | 
| 
       263 
263 
     | 
    
         
             
                end
         
     | 
| 
       264 
264 
     | 
    
         | 
| 
       265 
     | 
    
         
            -
                it  
     | 
| 
      
 265 
     | 
    
         
            +
                it 'fetches jobs ordered by priority' do
         
     | 
| 
       266 
266 
     | 
    
         
             
                  10.times { described_class.enqueue SimpleJob.new, :priority => rand(10) }
         
     | 
| 
       267 
267 
     | 
    
         
             
                  jobs = []
         
     | 
| 
       268 
268 
     | 
    
         
             
                  10.times { jobs << described_class.reserve(worker) }
         
     | 
| 
         @@ -272,10 +272,10 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       272 
272 
     | 
    
         
             
                  end
         
     | 
| 
       273 
273 
     | 
    
         
             
                end
         
     | 
| 
       274 
274 
     | 
    
         | 
| 
       275 
     | 
    
         
            -
                it  
     | 
| 
      
 275 
     | 
    
         
            +
                it 'only finds jobs greater than or equal to min priority' do
         
     | 
| 
       276 
276 
     | 
    
         
             
                  min = 5
         
     | 
| 
       277 
277 
     | 
    
         
             
                  Delayed::Worker.min_priority = min
         
     | 
| 
       278 
     | 
    
         
            -
                  [4,5,6].sort_by {| 
     | 
| 
      
 278 
     | 
    
         
            +
                  [4, 5, 6].sort_by { |_i| rand }.each { |i| create_job :priority => i }
         
     | 
| 
       279 
279 
     | 
    
         
             
                  2.times do
         
     | 
| 
       280 
280 
     | 
    
         
             
                    job = described_class.reserve(worker)
         
     | 
| 
       281 
281 
     | 
    
         
             
                    expect(job.priority).to be >= min
         
     | 
| 
         @@ -284,10 +284,10 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       284 
284 
     | 
    
         
             
                  expect(described_class.reserve(worker)).to be_nil
         
     | 
| 
       285 
285 
     | 
    
         
             
                end
         
     | 
| 
       286 
286 
     | 
    
         | 
| 
       287 
     | 
    
         
            -
                it  
     | 
| 
      
 287 
     | 
    
         
            +
                it 'only finds jobs less than or equal to max priority' do
         
     | 
| 
       288 
288 
     | 
    
         
             
                  max = 5
         
     | 
| 
       289 
289 
     | 
    
         
             
                  Delayed::Worker.max_priority = max
         
     | 
| 
       290 
     | 
    
         
            -
                  [4,5,6].sort_by {| 
     | 
| 
      
 290 
     | 
    
         
            +
                  [4, 5, 6].sort_by { |_i| rand }.each { |i| create_job :priority => i }
         
     | 
| 
       291 
291 
     | 
    
         
             
                  2.times do
         
     | 
| 
       292 
292 
     | 
    
         
             
                    job = described_class.reserve(worker)
         
     | 
| 
       293 
293 
     | 
    
         
             
                    expect(job.priority).to be <= max
         
     | 
| 
         @@ -297,73 +297,73 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       297 
297 
     | 
    
         
             
                end
         
     | 
| 
       298 
298 
     | 
    
         
             
              end
         
     | 
| 
       299 
299 
     | 
    
         | 
| 
       300 
     | 
    
         
            -
              context  
     | 
| 
      
 300 
     | 
    
         
            +
              context 'clear_locks!' do
         
     | 
| 
       301 
301 
     | 
    
         
             
                before do
         
     | 
| 
       302 
302 
     | 
    
         
             
                  @job = create_job(:locked_by => 'worker1', :locked_at => described_class.db_time_now)
         
     | 
| 
       303 
303 
     | 
    
         
             
                end
         
     | 
| 
       304 
304 
     | 
    
         | 
| 
       305 
     | 
    
         
            -
                it  
     | 
| 
      
 305 
     | 
    
         
            +
                it 'clears locks for the given worker' do
         
     | 
| 
       306 
306 
     | 
    
         
             
                  described_class.clear_locks!('worker1')
         
     | 
| 
       307 
307 
     | 
    
         
             
                  expect(described_class.reserve(worker)).to eq(@job)
         
     | 
| 
       308 
308 
     | 
    
         
             
                end
         
     | 
| 
       309 
309 
     | 
    
         | 
| 
       310 
     | 
    
         
            -
                it  
     | 
| 
      
 310 
     | 
    
         
            +
                it 'does not clear locks for other workers' do
         
     | 
| 
       311 
311 
     | 
    
         
             
                  described_class.clear_locks!('different_worker')
         
     | 
| 
       312 
312 
     | 
    
         
             
                  expect(described_class.reserve(worker)).not_to eq(@job)
         
     | 
| 
       313 
313 
     | 
    
         
             
                end
         
     | 
| 
       314 
314 
     | 
    
         
             
              end
         
     | 
| 
       315 
315 
     | 
    
         | 
| 
       316 
     | 
    
         
            -
              context  
     | 
| 
      
 316 
     | 
    
         
            +
              context 'unlock' do
         
     | 
| 
       317 
317 
     | 
    
         
             
                before do
         
     | 
| 
       318 
318 
     | 
    
         
             
                  @job = create_job(:locked_by => 'worker', :locked_at => described_class.db_time_now)
         
     | 
| 
       319 
319 
     | 
    
         
             
                end
         
     | 
| 
       320 
320 
     | 
    
         | 
| 
       321 
     | 
    
         
            -
                it  
     | 
| 
      
 321 
     | 
    
         
            +
                it 'clears locks' do
         
     | 
| 
       322 
322 
     | 
    
         
             
                  @job.unlock
         
     | 
| 
       323 
323 
     | 
    
         
             
                  expect(@job.locked_by).to be_nil
         
     | 
| 
       324 
324 
     | 
    
         
             
                  expect(@job.locked_at).to be_nil
         
     | 
| 
       325 
325 
     | 
    
         
             
                end
         
     | 
| 
       326 
326 
     | 
    
         
             
              end
         
     | 
| 
       327 
327 
     | 
    
         | 
| 
       328 
     | 
    
         
            -
              context  
     | 
| 
      
 328 
     | 
    
         
            +
              context 'large handler' do
         
     | 
| 
       329 
329 
     | 
    
         
             
                before do
         
     | 
| 
       330 
     | 
    
         
            -
                  text =  
     | 
| 
      
 330 
     | 
    
         
            +
                  text = 'Lorem ipsum dolor sit amet. ' * 1000
         
     | 
| 
       331 
331 
     | 
    
         
             
                  @job = described_class.enqueue Delayed::PerformableMethod.new(text, :length, {})
         
     | 
| 
       332 
332 
     | 
    
         
             
                end
         
     | 
| 
       333 
333 
     | 
    
         | 
| 
       334 
     | 
    
         
            -
                it  
     | 
| 
      
 334 
     | 
    
         
            +
                it 'has an id' do
         
     | 
| 
       335 
335 
     | 
    
         
             
                  expect(@job.id).not_to be_nil
         
     | 
| 
       336 
336 
     | 
    
         
             
                end
         
     | 
| 
       337 
337 
     | 
    
         
             
              end
         
     | 
| 
       338 
338 
     | 
    
         | 
| 
       339 
     | 
    
         
            -
              context  
     | 
| 
       340 
     | 
    
         
            -
                context  
     | 
| 
      
 339 
     | 
    
         
            +
              context 'named queues' do
         
     | 
| 
      
 340 
     | 
    
         
            +
                context 'when worker has one queue set' do
         
     | 
| 
       341 
341 
     | 
    
         
             
                  before(:each) do
         
     | 
| 
       342 
342 
     | 
    
         
             
                    worker.queues = ['large']
         
     | 
| 
       343 
343 
     | 
    
         
             
                  end
         
     | 
| 
       344 
344 
     | 
    
         | 
| 
       345 
     | 
    
         
            -
                  it  
     | 
| 
      
 345 
     | 
    
         
            +
                  it 'only works off jobs which are from its queue' do
         
     | 
| 
       346 
346 
     | 
    
         
             
                    expect(SimpleJob.runs).to eq(0)
         
     | 
| 
       347 
347 
     | 
    
         | 
| 
       348 
     | 
    
         
            -
                    create_job(:queue =>  
     | 
| 
       349 
     | 
    
         
            -
                    create_job(:queue =>  
     | 
| 
      
 348 
     | 
    
         
            +
                    create_job(:queue => 'large')
         
     | 
| 
      
 349 
     | 
    
         
            +
                    create_job(:queue => 'small')
         
     | 
| 
       350 
350 
     | 
    
         
             
                    worker.work_off
         
     | 
| 
       351 
351 
     | 
    
         | 
| 
       352 
352 
     | 
    
         
             
                    expect(SimpleJob.runs).to eq(1)
         
     | 
| 
       353 
353 
     | 
    
         
             
                  end
         
     | 
| 
       354 
354 
     | 
    
         
             
                end
         
     | 
| 
       355 
355 
     | 
    
         | 
| 
       356 
     | 
    
         
            -
                context  
     | 
| 
      
 356 
     | 
    
         
            +
                context 'when worker has two queue set' do
         
     | 
| 
       357 
357 
     | 
    
         
             
                  before(:each) do
         
     | 
| 
       358 
     | 
    
         
            -
                    worker.queues = [ 
     | 
| 
      
 358 
     | 
    
         
            +
                    worker.queues = %w[large small]
         
     | 
| 
       359 
359 
     | 
    
         
             
                  end
         
     | 
| 
       360 
360 
     | 
    
         | 
| 
       361 
     | 
    
         
            -
                  it  
     | 
| 
      
 361 
     | 
    
         
            +
                  it 'only works off jobs which are from its queue' do
         
     | 
| 
       362 
362 
     | 
    
         
             
                    expect(SimpleJob.runs).to eq(0)
         
     | 
| 
       363 
363 
     | 
    
         | 
| 
       364 
     | 
    
         
            -
                    create_job(:queue =>  
     | 
| 
       365 
     | 
    
         
            -
                    create_job(:queue =>  
     | 
| 
       366 
     | 
    
         
            -
                    create_job(:queue =>  
     | 
| 
      
 364 
     | 
    
         
            +
                    create_job(:queue => 'large')
         
     | 
| 
      
 365 
     | 
    
         
            +
                    create_job(:queue => 'small')
         
     | 
| 
      
 366 
     | 
    
         
            +
                    create_job(:queue => 'medium')
         
     | 
| 
       367 
367 
     | 
    
         
             
                    create_job
         
     | 
| 
       368 
368 
     | 
    
         
             
                    worker.work_off
         
     | 
| 
       369 
369 
     | 
    
         | 
| 
         @@ -371,16 +371,16 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       371 
371 
     | 
    
         
             
                  end
         
     | 
| 
       372 
372 
     | 
    
         
             
                end
         
     | 
| 
       373 
373 
     | 
    
         | 
| 
       374 
     | 
    
         
            -
                context  
     | 
| 
      
 374 
     | 
    
         
            +
                context 'when worker does not have queue set' do
         
     | 
| 
       375 
375 
     | 
    
         
             
                  before(:each) do
         
     | 
| 
       376 
376 
     | 
    
         
             
                    worker.queues = []
         
     | 
| 
       377 
377 
     | 
    
         
             
                  end
         
     | 
| 
       378 
378 
     | 
    
         | 
| 
       379 
     | 
    
         
            -
                  it  
     | 
| 
      
 379 
     | 
    
         
            +
                  it 'works off all jobs' do
         
     | 
| 
       380 
380 
     | 
    
         
             
                    expect(SimpleJob.runs).to eq(0)
         
     | 
| 
       381 
381 
     | 
    
         | 
| 
       382 
     | 
    
         
            -
                    create_job(:queue =>  
     | 
| 
       383 
     | 
    
         
            -
                    create_job(:queue =>  
     | 
| 
      
 382 
     | 
    
         
            +
                    create_job(:queue => 'one')
         
     | 
| 
      
 383 
     | 
    
         
            +
                    create_job(:queue => 'two')
         
     | 
| 
       384 
384 
     | 
    
         
             
                    create_job
         
     | 
| 
       385 
385 
     | 
    
         
             
                    worker.work_off
         
     | 
| 
       386 
386 
     | 
    
         | 
| 
         @@ -389,84 +389,78 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       389 
389 
     | 
    
         
             
                end
         
     | 
| 
       390 
390 
     | 
    
         
             
              end
         
     | 
| 
       391 
391 
     | 
    
         | 
| 
       392 
     | 
    
         
            -
              context  
     | 
| 
      
 392 
     | 
    
         
            +
              context 'max_attempts' do
         
     | 
| 
       393 
393 
     | 
    
         
             
                before(:each) do
         
     | 
| 
       394 
394 
     | 
    
         
             
                  @job = described_class.enqueue SimpleJob.new
         
     | 
| 
       395 
395 
     | 
    
         
             
                end
         
     | 
| 
       396 
396 
     | 
    
         | 
| 
       397 
     | 
    
         
            -
                it  
     | 
| 
      
 397 
     | 
    
         
            +
                it 'is not defined' do
         
     | 
| 
       398 
398 
     | 
    
         
             
                  expect(@job.max_attempts).to be_nil
         
     | 
| 
       399 
399 
     | 
    
         
             
                end
         
     | 
| 
       400 
400 
     | 
    
         | 
| 
       401 
     | 
    
         
            -
                it  
     | 
| 
      
 401 
     | 
    
         
            +
                it 'uses the max_retries value on the payload when defined' do
         
     | 
| 
       402 
402 
     | 
    
         
             
                  expect(@job.payload_object).to receive(:max_attempts).and_return(99)
         
     | 
| 
       403 
403 
     | 
    
         
             
                  expect(@job.max_attempts).to eq(99)
         
     | 
| 
       404 
404 
     | 
    
         
             
                end
         
     | 
| 
       405 
405 
     | 
    
         
             
              end
         
     | 
| 
       406 
406 
     | 
    
         | 
| 
       407 
     | 
    
         
            -
              describe  
     | 
| 
       408 
     | 
    
         
            -
                context  
     | 
| 
       409 
     | 
    
         
            -
                  it  
     | 
| 
      
 407 
     | 
    
         
            +
              describe 'yaml serialization' do
         
     | 
| 
      
 408 
     | 
    
         
            +
                context 'when serializing jobs' do
         
     | 
| 
      
 409 
     | 
    
         
            +
                  it 'raises error ArgumentError for new records' do
         
     | 
| 
       410 
410 
     | 
    
         
             
                    story = Story.new(:text => 'hello')
         
     | 
| 
       411 
411 
     | 
    
         
             
                    if story.respond_to?(:new_record?)
         
     | 
| 
       412 
     | 
    
         
            -
                      expect {
         
     | 
| 
       413 
     | 
    
         
            -
                        story.delay.tell
         
     | 
| 
       414 
     | 
    
         
            -
                      }.to raise_error(ArgumentError, 'Jobs cannot be created for non-persisted records')
         
     | 
| 
      
 412 
     | 
    
         
            +
                      expect { story.delay.tell }.to raise_error(ArgumentError, 'Jobs cannot be created for non-persisted records')
         
     | 
| 
       415 
413 
     | 
    
         
             
                    end
         
     | 
| 
       416 
414 
     | 
    
         
             
                  end
         
     | 
| 
       417 
415 
     | 
    
         | 
| 
       418 
     | 
    
         
            -
                  it  
     | 
| 
      
 416 
     | 
    
         
            +
                  it 'raises error ArgumentError for destroyed records' do
         
     | 
| 
       419 
417 
     | 
    
         
             
                    story = Story.create(:text => 'hello')
         
     | 
| 
       420 
418 
     | 
    
         
             
                    story.destroy
         
     | 
| 
       421 
     | 
    
         
            -
                    expect {
         
     | 
| 
       422 
     | 
    
         
            -
                      story.delay.tell
         
     | 
| 
       423 
     | 
    
         
            -
                    }.to raise_error(ArgumentError, 'Jobs cannot be created for non-persisted records')
         
     | 
| 
      
 419 
     | 
    
         
            +
                    expect { story.delay.tell }.to raise_error(ArgumentError, 'Jobs cannot be created for non-persisted records')
         
     | 
| 
       424 
420 
     | 
    
         
             
                  end
         
     | 
| 
       425 
421 
     | 
    
         
             
                end
         
     | 
| 
       426 
422 
     | 
    
         | 
| 
       427 
     | 
    
         
            -
                context  
     | 
| 
       428 
     | 
    
         
            -
                  it  
     | 
| 
      
 423 
     | 
    
         
            +
                context 'when reload jobs back' do
         
     | 
| 
      
 424 
     | 
    
         
            +
                  it 'reloads changed attributes' do
         
     | 
| 
       429 
425 
     | 
    
         
             
                    story = Story.create(:text => 'hello')
         
     | 
| 
       430 
426 
     | 
    
         
             
                    job = story.delay.tell
         
     | 
| 
       431 
427 
     | 
    
         
             
                    story.update_attributes :text => 'goodbye'
         
     | 
| 
       432 
428 
     | 
    
         
             
                    expect(job.reload.payload_object.object.text).to eq('goodbye')
         
     | 
| 
       433 
429 
     | 
    
         
             
                  end
         
     | 
| 
       434 
430 
     | 
    
         | 
| 
       435 
     | 
    
         
            -
                  it  
     | 
| 
      
 431 
     | 
    
         
            +
                  it 'raises deserialization error for destroyed records' do
         
     | 
| 
       436 
432 
     | 
    
         
             
                    story = Story.create(:text => 'hello')
         
     | 
| 
       437 
433 
     | 
    
         
             
                    job = story.delay.tell
         
     | 
| 
       438 
434 
     | 
    
         
             
                    story.destroy
         
     | 
| 
       439 
     | 
    
         
            -
                    expect {
         
     | 
| 
       440 
     | 
    
         
            -
                      job.reload.payload_object
         
     | 
| 
       441 
     | 
    
         
            -
                    }.to raise_error(Delayed::DeserializationError)
         
     | 
| 
      
 435 
     | 
    
         
            +
                    expect { job.reload.payload_object }.to raise_error(Delayed::DeserializationError)
         
     | 
| 
       442 
436 
     | 
    
         
             
                  end
         
     | 
| 
       443 
437 
     | 
    
         
             
                end
         
     | 
| 
       444 
438 
     | 
    
         
             
              end
         
     | 
| 
       445 
439 
     | 
    
         | 
| 
       446 
     | 
    
         
            -
              describe  
     | 
| 
      
 440 
     | 
    
         
            +
              describe 'worker integration' do
         
     | 
| 
       447 
441 
     | 
    
         
             
                before do
         
     | 
| 
       448 
442 
     | 
    
         
             
                  Delayed::Job.delete_all
         
     | 
| 
       449 
443 
     | 
    
         
             
                  SimpleJob.runs = 0
         
     | 
| 
       450 
444 
     | 
    
         
             
                end
         
     | 
| 
       451 
445 
     | 
    
         | 
| 
       452 
     | 
    
         
            -
                describe  
     | 
| 
       453 
     | 
    
         
            -
                  it  
     | 
| 
      
 446 
     | 
    
         
            +
                describe 'running a job' do
         
     | 
| 
      
 447 
     | 
    
         
            +
                  it 'fails after Worker.max_run_time' do
         
     | 
| 
       454 
448 
     | 
    
         
             
                    Delayed::Worker.max_run_time = 1.second
         
     | 
| 
       455 
449 
     | 
    
         
             
                    job = Delayed::Job.create :payload_object => LongRunningJob.new
         
     | 
| 
       456 
450 
     | 
    
         
             
                    worker.run(job)
         
     | 
| 
       457 
451 
     | 
    
         
             
                    expect(job.reload.last_error).to match(/expired/)
         
     | 
| 
       458 
     | 
    
         
            -
                    expect(job.reload.last_error).to match(/Delayed::Worker 
     | 
| 
      
 452 
     | 
    
         
            +
                    expect(job.reload.last_error).to match(/Delayed::Worker\.max_run_time is only 1 second/)
         
     | 
| 
       459 
453 
     | 
    
         
             
                    expect(job.attempts).to eq(1)
         
     | 
| 
       460 
454 
     | 
    
         
             
                  end
         
     | 
| 
       461 
455 
     | 
    
         | 
| 
       462 
     | 
    
         
            -
                  context  
     | 
| 
      
 456 
     | 
    
         
            +
                  context 'when the job raises a deserialization error' do
         
     | 
| 
       463 
457 
     | 
    
         
             
                    after do
         
     | 
| 
       464 
458 
     | 
    
         
             
                      Delayed::Worker.destroy_failed_jobs = true
         
     | 
| 
       465 
459 
     | 
    
         
             
                    end
         
     | 
| 
       466 
460 
     | 
    
         | 
| 
       467 
     | 
    
         
            -
                    it  
     | 
| 
      
 461 
     | 
    
         
            +
                    it 'marks the job as failed' do
         
     | 
| 
       468 
462 
     | 
    
         
             
                      Delayed::Worker.destroy_failed_jobs = false
         
     | 
| 
       469 
     | 
    
         
            -
                      job = described_class.create! :handler =>  
     | 
| 
      
 463 
     | 
    
         
            +
                      job = described_class.create! :handler => '--- !ruby/object:JobThatDoesNotExist {}'
         
     | 
| 
       470 
464 
     | 
    
         
             
                      worker.work_off
         
     | 
| 
       471 
465 
     | 
    
         
             
                      job.reload
         
     | 
| 
       472 
466 
     | 
    
         
             
                      expect(job).to be_failed
         
     | 
| 
         @@ -474,7 +468,7 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       474 
468 
     | 
    
         
             
                  end
         
     | 
| 
       475 
469 
     | 
    
         
             
                end
         
     | 
| 
       476 
470 
     | 
    
         | 
| 
       477 
     | 
    
         
            -
                describe  
     | 
| 
      
 471 
     | 
    
         
            +
                describe 'failed jobs' do
         
     | 
| 
       478 
472 
     | 
    
         
             
                  before do
         
     | 
| 
       479 
473 
     | 
    
         
             
                    @job = Delayed::Job.enqueue(ErrorJob.new, :run_at => described_class.db_time_now - 1)
         
     | 
| 
       480 
474 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -484,7 +478,7 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       484 
478 
     | 
    
         
             
                    Delayed::Worker.destroy_failed_jobs = true
         
     | 
| 
       485 
479 
     | 
    
         
             
                  end
         
     | 
| 
       486 
480 
     | 
    
         | 
| 
       487 
     | 
    
         
            -
                  it  
     | 
| 
      
 481 
     | 
    
         
            +
                  it 'records last_error when destroy_failed_jobs = false, max_attempts = 1' do
         
     | 
| 
       488 
482 
     | 
    
         
             
                    Delayed::Worker.destroy_failed_jobs = false
         
     | 
| 
       489 
483 
     | 
    
         
             
                    Delayed::Worker.max_attempts = 1
         
     | 
| 
       490 
484 
     | 
    
         
             
                    worker.run(@job)
         
     | 
| 
         @@ -494,7 +488,7 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       494 
488 
     | 
    
         
             
                    expect(@job).to be_failed
         
     | 
| 
       495 
489 
     | 
    
         
             
                  end
         
     | 
| 
       496 
490 
     | 
    
         | 
| 
       497 
     | 
    
         
            -
                  it  
     | 
| 
      
 491 
     | 
    
         
            +
                  it 're-schedules jobs after failing' do
         
     | 
| 
       498 
492 
     | 
    
         
             
                    worker.work_off
         
     | 
| 
       499 
493 
     | 
    
         
             
                    @job.reload
         
     | 
| 
       500 
494 
     | 
    
         
             
                    expect(@job.last_error).to match(/did not work/)
         
     | 
| 
         @@ -506,7 +500,7 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       506 
500 
     | 
    
         
             
                    expect(@job.locked_at).to be_nil
         
     | 
| 
       507 
501 
     | 
    
         
             
                  end
         
     | 
| 
       508 
502 
     | 
    
         | 
| 
       509 
     | 
    
         
            -
                  it  
     | 
| 
      
 503 
     | 
    
         
            +
                  it 're-schedules jobs with handler provided time if present' do
         
     | 
| 
       510 
504 
     | 
    
         
             
                    job = Delayed::Job.enqueue(CustomRescheduleJob.new(99.minutes))
         
     | 
| 
       511 
505 
     | 
    
         
             
                    worker.run(job)
         
     | 
| 
       512 
506 
     | 
    
         
             
                    job.reload
         
     | 
| 
         @@ -518,26 +512,33 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       518 
512 
     | 
    
         
             
                    error_with_nil_message = StandardError.new
         
     | 
| 
       519 
513 
     | 
    
         
             
                    expect(error_with_nil_message).to receive(:message).twice.and_return(nil)
         
     | 
| 
       520 
514 
     | 
    
         
             
                    expect(@job).to receive(:invoke_job).and_raise error_with_nil_message
         
     | 
| 
       521 
     | 
    
         
            -
                    expect{worker.run(@job)}.not_to raise_error
         
     | 
| 
      
 515 
     | 
    
         
            +
                    expect { worker.run(@job) }.not_to raise_error
         
     | 
| 
       522 
516 
     | 
    
         
             
                  end
         
     | 
| 
       523 
517 
     | 
    
         
             
                end
         
     | 
| 
       524 
518 
     | 
    
         | 
| 
       525 
     | 
    
         
            -
                context  
     | 
| 
      
 519 
     | 
    
         
            +
                context 'reschedule' do
         
     | 
| 
       526 
520 
     | 
    
         
             
                  before do
         
     | 
| 
       527 
521 
     | 
    
         
             
                    @job = Delayed::Job.create :payload_object => SimpleJob.new
         
     | 
| 
       528 
522 
     | 
    
         
             
                  end
         
     | 
| 
       529 
523 
     | 
    
         | 
| 
       530 
     | 
    
         
            -
                  shared_examples_for  
     | 
| 
      
 524 
     | 
    
         
            +
                  shared_examples_for 'any failure more than Worker.max_attempts times' do
         
     | 
| 
       531 
525 
     | 
    
         
             
                    context "when the job's payload has a #failure hook" do
         
     | 
| 
       532 
526 
     | 
    
         
             
                      before do
         
     | 
| 
       533 
527 
     | 
    
         
             
                        @job = Delayed::Job.create :payload_object => OnPermanentFailureJob.new
         
     | 
| 
       534 
528 
     | 
    
         
             
                        expect(@job.payload_object).to respond_to(:failure)
         
     | 
| 
       535 
529 
     | 
    
         
             
                      end
         
     | 
| 
       536 
530 
     | 
    
         | 
| 
       537 
     | 
    
         
            -
                      it  
     | 
| 
      
 531 
     | 
    
         
            +
                      it 'runs that hook' do
         
     | 
| 
       538 
532 
     | 
    
         
             
                        expect(@job.payload_object).to receive(:failure)
         
     | 
| 
       539 
533 
     | 
    
         
             
                        worker.reschedule(@job)
         
     | 
| 
       540 
534 
     | 
    
         
             
                      end
         
     | 
| 
      
 535 
     | 
    
         
            +
             
     | 
| 
      
 536 
     | 
    
         
            +
                      it 'handles error in hook' do
         
     | 
| 
      
 537 
     | 
    
         
            +
                        Delayed::Worker.destroy_failed_jobs = false
         
     | 
| 
      
 538 
     | 
    
         
            +
                        @job.payload_object.raise_error = true
         
     | 
| 
      
 539 
     | 
    
         
            +
                        expect { worker.reschedule(@job) }.not_to raise_error
         
     | 
| 
      
 540 
     | 
    
         
            +
                        expect(@job.failed_at).to_not be_nil
         
     | 
| 
      
 541 
     | 
    
         
            +
                      end
         
     | 
| 
       541 
542 
     | 
    
         
             
                    end
         
     | 
| 
       542 
543 
     | 
    
         | 
| 
       543 
544 
     | 
    
         
             
                    context "when the job's payload has no #failure hook" do
         
     | 
| 
         @@ -555,23 +556,23 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       555 
556 
     | 
    
         
             
                        expect(@job.payload_object).not_to respond_to(:failure)
         
     | 
| 
       556 
557 
     | 
    
         
             
                      end
         
     | 
| 
       557 
558 
     | 
    
         | 
| 
       558 
     | 
    
         
            -
                      it  
     | 
| 
       559 
     | 
    
         
            -
                        expect  
     | 
| 
      
 559 
     | 
    
         
            +
                      it 'does not try to run that hook' do
         
     | 
| 
      
 560 
     | 
    
         
            +
                        expect do
         
     | 
| 
       560 
561 
     | 
    
         
             
                          Delayed::Worker.max_attempts.times { worker.reschedule(@job) }
         
     | 
| 
       561 
     | 
    
         
            -
                         
     | 
| 
      
 562 
     | 
    
         
            +
                        end.not_to raise_exception
         
     | 
| 
       562 
563 
     | 
    
         
             
                      end
         
     | 
| 
       563 
564 
     | 
    
         
             
                    end
         
     | 
| 
       564 
565 
     | 
    
         
             
                  end
         
     | 
| 
       565 
566 
     | 
    
         | 
| 
       566 
     | 
    
         
            -
                  context  
     | 
| 
       567 
     | 
    
         
            -
                     
     | 
| 
      
 567 
     | 
    
         
            +
                  context 'and we want to destroy jobs' do
         
     | 
| 
      
 568 
     | 
    
         
            +
                    it_behaves_like 'any failure more than Worker.max_attempts times'
         
     | 
| 
       568 
569 
     | 
    
         | 
| 
       569 
     | 
    
         
            -
                    it  
     | 
| 
      
 570 
     | 
    
         
            +
                    it 'is destroyed if it failed more than Worker.max_attempts times' do
         
     | 
| 
       570 
571 
     | 
    
         
             
                      expect(@job).to receive(:destroy)
         
     | 
| 
       571 
572 
     | 
    
         
             
                      Delayed::Worker.max_attempts.times { worker.reschedule(@job) }
         
     | 
| 
       572 
573 
     | 
    
         
             
                    end
         
     | 
| 
       573 
574 
     | 
    
         | 
| 
       574 
     | 
    
         
            -
                    it  
     | 
| 
      
 575 
     | 
    
         
            +
                    it 'is not destroyed if failed fewer than Worker.max_attempts times' do
         
     | 
| 
       575 
576 
     | 
    
         
             
                      expect(@job).not_to receive(:destroy)
         
     | 
| 
       576 
577 
     | 
    
         
             
                      (Delayed::Worker.max_attempts - 1).times { worker.reschedule(@job) }
         
     | 
| 
       577 
578 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -586,15 +587,15 @@ shared_examples_for "a delayed_job backend" do 
     | 
|
| 
       586 
587 
     | 
    
         
             
                      Delayed::Worker.destroy_failed_jobs = true
         
     | 
| 
       587 
588 
     | 
    
         
             
                    end
         
     | 
| 
       588 
589 
     | 
    
         | 
| 
       589 
     | 
    
         
            -
                     
     | 
| 
      
 590 
     | 
    
         
            +
                    it_behaves_like 'any failure more than Worker.max_attempts times'
         
     | 
| 
       590 
591 
     | 
    
         | 
| 
       591 
     | 
    
         
            -
                    it  
     | 
| 
      
 592 
     | 
    
         
            +
                    it 'is failed if it failed more than Worker.max_attempts times' do
         
     | 
| 
       592 
593 
     | 
    
         
             
                      expect(@job.reload).not_to be_failed
         
     | 
| 
       593 
594 
     | 
    
         
             
                      Delayed::Worker.max_attempts.times { worker.reschedule(@job) }
         
     | 
| 
       594 
595 
     | 
    
         
             
                      expect(@job.reload).to be_failed
         
     | 
| 
       595 
596 
     | 
    
         
             
                    end
         
     | 
| 
       596 
597 
     | 
    
         | 
| 
       597 
     | 
    
         
            -
                    it  
     | 
| 
      
 598 
     | 
    
         
            +
                    it 'is not failed if it failed fewer than Worker.max_attempts times' do
         
     | 
| 
       598 
599 
     | 
    
         
             
                      (Delayed::Worker.max_attempts - 1).times { worker.reschedule(@job) }
         
     | 
| 
       599 
600 
     | 
    
         
             
                      expect(@job.reload).not_to be_failed
         
     | 
| 
       600 
601 
     | 
    
         
             
                    end
         
     |