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
 
    
        data/lib/delayed/command.rb
    CHANGED
    
    | 
         @@ -1,15 +1,17 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
               
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
               
     | 
| 
      
 1 
     | 
    
         
            +
            unless ENV['RAILS_ENV'] == 'test'
         
     | 
| 
      
 2 
     | 
    
         
            +
              begin
         
     | 
| 
      
 3 
     | 
    
         
            +
                require 'daemons'
         
     | 
| 
      
 4 
     | 
    
         
            +
              rescue LoadError
         
     | 
| 
      
 5 
     | 
    
         
            +
                raise "You need to add gem 'daemons' to your Gemfile if you wish to use it."
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
       5 
7 
     | 
    
         
             
            end
         
     | 
| 
       6 
8 
     | 
    
         
             
            require 'optparse'
         
     | 
| 
       7 
9 
     | 
    
         | 
| 
       8 
10 
     | 
    
         
             
            module Delayed
         
     | 
| 
       9 
     | 
    
         
            -
              class Command
         
     | 
| 
       10 
     | 
    
         
            -
                attr_accessor :worker_count
         
     | 
| 
      
 11 
     | 
    
         
            +
              class Command # rubocop:disable ClassLength
         
     | 
| 
      
 12 
     | 
    
         
            +
                attr_accessor :worker_count, :worker_pools
         
     | 
| 
       11 
13 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                def initialize(args)
         
     | 
| 
      
 14 
     | 
    
         
            +
                def initialize(args) # rubocop:disable MethodLength
         
     | 
| 
       13 
15 
     | 
    
         
             
                  @options = {
         
     | 
| 
       14 
16 
     | 
    
         
             
                    :quiet => true,
         
     | 
| 
       15 
17 
     | 
    
         
             
                    :pid_dir => "#{Rails.root}/tmp/pids"
         
     | 
| 
         @@ -18,88 +20,106 @@ module Delayed 
     | 
|
| 
       18 
20 
     | 
    
         
             
                  @worker_count = 1
         
     | 
| 
       19 
21 
     | 
    
         
             
                  @monitor = false
         
     | 
| 
       20 
22 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                  opts = OptionParser.new do | 
     | 
| 
       22 
     | 
    
         
            -
                     
     | 
| 
      
 23 
     | 
    
         
            +
                  opts = OptionParser.new do |opt|
         
     | 
| 
      
 24 
     | 
    
         
            +
                    opt.banner = "Usage: #{File.basename($PROGRAM_NAME)} [options] start|stop|restart|run"
         
     | 
| 
       23 
25 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                     
     | 
| 
       25 
     | 
    
         
            -
                      puts  
     | 
| 
      
 26 
     | 
    
         
            +
                    opt.on('-h', '--help', 'Show this message') do
         
     | 
| 
      
 27 
     | 
    
         
            +
                      puts opt
         
     | 
| 
       26 
28 
     | 
    
         
             
                      exit 1
         
     | 
| 
       27 
29 
     | 
    
         
             
                    end
         
     | 
| 
       28 
     | 
    
         
            -
                     
     | 
| 
       29 
     | 
    
         
            -
                      STDERR.puts  
     | 
| 
      
 30 
     | 
    
         
            +
                    opt.on('-e', '--environment=NAME', 'Specifies the environment to run this delayed jobs under (test/development/production).') do |_e|
         
     | 
| 
      
 31 
     | 
    
         
            +
                      STDERR.puts 'The -e/--environment option has been deprecated and has no effect. Use RAILS_ENV and see http://github.com/collectiveidea/delayed_job/issues/#issue/7'
         
     | 
| 
       30 
32 
     | 
    
         
             
                    end
         
     | 
| 
       31 
     | 
    
         
            -
                     
     | 
| 
      
 33 
     | 
    
         
            +
                    opt.on('--min-priority N', 'Minimum priority of jobs to run.') do |n|
         
     | 
| 
       32 
34 
     | 
    
         
             
                      @options[:min_priority] = n
         
     | 
| 
       33 
35 
     | 
    
         
             
                    end
         
     | 
| 
       34 
     | 
    
         
            -
                     
     | 
| 
      
 36 
     | 
    
         
            +
                    opt.on('--max-priority N', 'Maximum priority of jobs to run.') do |n|
         
     | 
| 
       35 
37 
     | 
    
         
             
                      @options[:max_priority] = n
         
     | 
| 
       36 
38 
     | 
    
         
             
                    end
         
     | 
| 
       37 
     | 
    
         
            -
                     
     | 
| 
       38 
     | 
    
         
            -
                      @worker_count = worker_count.to_i rescue 1
         
     | 
| 
      
 39 
     | 
    
         
            +
                    opt.on('-n', '--number_of_workers=workers', 'Number of unique workers to spawn') do |worker_count|
         
     | 
| 
      
 40 
     | 
    
         
            +
                      @worker_count = worker_count.to_i rescue 1 # rubocop:disable RescueModifier
         
     | 
| 
       39 
41 
     | 
    
         
             
                    end
         
     | 
| 
       40 
     | 
    
         
            -
                     
     | 
| 
      
 42 
     | 
    
         
            +
                    opt.on('--pid-dir=DIR', 'Specifies an alternate directory in which to store the process ids.') do |dir|
         
     | 
| 
       41 
43 
     | 
    
         
             
                      @options[:pid_dir] = dir
         
     | 
| 
       42 
44 
     | 
    
         
             
                    end
         
     | 
| 
       43 
     | 
    
         
            -
                     
     | 
| 
      
 45 
     | 
    
         
            +
                    opt.on('-i', '--identifier=n', 'A numeric identifier for the worker.') do |n|
         
     | 
| 
       44 
46 
     | 
    
         
             
                      @options[:identifier] = n
         
     | 
| 
       45 
47 
     | 
    
         
             
                    end
         
     | 
| 
       46 
     | 
    
         
            -
                     
     | 
| 
      
 48 
     | 
    
         
            +
                    opt.on('-m', '--monitor', 'Start monitor process.') do
         
     | 
| 
       47 
49 
     | 
    
         
             
                      @monitor = true
         
     | 
| 
       48 
50 
     | 
    
         
             
                    end
         
     | 
| 
       49 
     | 
    
         
            -
                     
     | 
| 
      
 51 
     | 
    
         
            +
                    opt.on('--sleep-delay N', 'Amount of time to sleep when no jobs are found') do |n|
         
     | 
| 
       50 
52 
     | 
    
         
             
                      @options[:sleep_delay] = n.to_i
         
     | 
| 
       51 
53 
     | 
    
         
             
                    end
         
     | 
| 
       52 
     | 
    
         
            -
                     
     | 
| 
      
 54 
     | 
    
         
            +
                    opt.on('--read-ahead N', 'Number of jobs from the queue to consider') do |n|
         
     | 
| 
       53 
55 
     | 
    
         
             
                      @options[:read_ahead] = n
         
     | 
| 
       54 
56 
     | 
    
         
             
                    end
         
     | 
| 
       55 
     | 
    
         
            -
                     
     | 
| 
      
 57 
     | 
    
         
            +
                    opt.on('-p', '--prefix NAME', 'String to be prefixed to worker process names') do |prefix|
         
     | 
| 
       56 
58 
     | 
    
         
             
                      @options[:prefix] = prefix
         
     | 
| 
       57 
59 
     | 
    
         
             
                    end
         
     | 
| 
       58 
     | 
    
         
            -
                     
     | 
| 
      
 60 
     | 
    
         
            +
                    opt.on('--queues=queues', 'Specify which queue DJ must look up for jobs') do |queues|
         
     | 
| 
       59 
61 
     | 
    
         
             
                      @options[:queues] = queues.split(',')
         
     | 
| 
       60 
62 
     | 
    
         
             
                    end
         
     | 
| 
       61 
     | 
    
         
            -
                     
     | 
| 
      
 63 
     | 
    
         
            +
                    opt.on('--queue=queue', 'Specify which queue DJ must look up for jobs') do |queue|
         
     | 
| 
       62 
64 
     | 
    
         
             
                      @options[:queues] = queue.split(',')
         
     | 
| 
       63 
65 
     | 
    
         
             
                    end
         
     | 
| 
       64 
     | 
    
         
            -
                     
     | 
| 
      
 66 
     | 
    
         
            +
                    opt.on('--pool=queue1[,queue2][:worker_count]', 'Specify queues and number of workers for a worker pool') do |pool|
         
     | 
| 
      
 67 
     | 
    
         
            +
                      parse_worker_pool(pool)
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
                    opt.on('--exit-on-complete', 'Exit when no more jobs are available to run. This will exit if all jobs are scheduled to run in the future.') do
         
     | 
| 
       65 
70 
     | 
    
         
             
                      @options[:exit_on_complete] = true
         
     | 
| 
       66 
71 
     | 
    
         
             
                    end
         
     | 
| 
       67 
72 
     | 
    
         
             
                  end
         
     | 
| 
       68 
73 
     | 
    
         
             
                  @args = opts.parse!(args)
         
     | 
| 
       69 
74 
     | 
    
         
             
                end
         
     | 
| 
       70 
75 
     | 
    
         | 
| 
       71 
     | 
    
         
            -
                def daemonize
         
     | 
| 
      
 76 
     | 
    
         
            +
                def daemonize # rubocop:disable PerceivedComplexity
         
     | 
| 
       72 
77 
     | 
    
         
             
                  dir = @options[:pid_dir]
         
     | 
| 
       73 
     | 
    
         
            -
                  Dir.mkdir(dir) unless File. 
     | 
| 
      
 78 
     | 
    
         
            +
                  Dir.mkdir(dir) unless File.exist?(dir)
         
     | 
| 
       74 
79 
     | 
    
         | 
| 
       75 
     | 
    
         
            -
                  if  
     | 
| 
       76 
     | 
    
         
            -
                     
     | 
| 
       77 
     | 
    
         
            -
                  elsif @ 
     | 
| 
       78 
     | 
    
         
            -
                     
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
      
 80 
     | 
    
         
            +
                  if worker_pools
         
     | 
| 
      
 81 
     | 
    
         
            +
                    setup_pools
         
     | 
| 
      
 82 
     | 
    
         
            +
                  elsif @options[:identifier]
         
     | 
| 
      
 83 
     | 
    
         
            +
                    if worker_count > 1
         
     | 
| 
      
 84 
     | 
    
         
            +
                      raise ArgumentError, 'Cannot specify both --number-of-workers and --identifier'
         
     | 
| 
      
 85 
     | 
    
         
            +
                    else
         
     | 
| 
      
 86 
     | 
    
         
            +
                      run_process("delayed_job.#{@options[:identifier]}", @options)
         
     | 
| 
      
 87 
     | 
    
         
            +
                    end
         
     | 
| 
       80 
88 
     | 
    
         
             
                  else
         
     | 
| 
       81 
89 
     | 
    
         
             
                    worker_count.times do |worker_index|
         
     | 
| 
       82 
     | 
    
         
            -
                      process_name = worker_count == 1 ?  
     | 
| 
       83 
     | 
    
         
            -
                      run_process(process_name,  
     | 
| 
      
 90 
     | 
    
         
            +
                      process_name = worker_count == 1 ? 'delayed_job' : "delayed_job.#{worker_index}"
         
     | 
| 
      
 91 
     | 
    
         
            +
                      run_process(process_name, @options)
         
     | 
| 
      
 92 
     | 
    
         
            +
                    end
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                def setup_pools
         
     | 
| 
      
 97 
     | 
    
         
            +
                  worker_index = 0
         
     | 
| 
      
 98 
     | 
    
         
            +
                  @worker_pools.each do |queues, worker_count|
         
     | 
| 
      
 99 
     | 
    
         
            +
                    options = @options.merge(:queues => queues)
         
     | 
| 
      
 100 
     | 
    
         
            +
                    worker_count.times do
         
     | 
| 
      
 101 
     | 
    
         
            +
                      process_name = "delayed_job.#{worker_index}"
         
     | 
| 
      
 102 
     | 
    
         
            +
                      run_process(process_name, options)
         
     | 
| 
      
 103 
     | 
    
         
            +
                      worker_index += 1
         
     | 
| 
       84 
104 
     | 
    
         
             
                    end
         
     | 
| 
       85 
105 
     | 
    
         
             
                  end
         
     | 
| 
       86 
106 
     | 
    
         
             
                end
         
     | 
| 
       87 
107 
     | 
    
         | 
| 
       88 
     | 
    
         
            -
                def run_process(process_name,  
     | 
| 
      
 108 
     | 
    
         
            +
                def run_process(process_name, options = {})
         
     | 
| 
       89 
109 
     | 
    
         
             
                  Delayed::Worker.before_fork
         
     | 
| 
       90 
     | 
    
         
            -
                  Daemons.run_proc(process_name, :dir =>  
     | 
| 
       91 
     | 
    
         
            -
                    $0 = File.join( 
     | 
| 
      
 110 
     | 
    
         
            +
                  Daemons.run_proc(process_name, :dir => options[:pid_dir], :dir_mode => :normal, :monitor => @monitor, :ARGV => @args) do |*_args|
         
     | 
| 
      
 111 
     | 
    
         
            +
                    $0 = File.join(options[:prefix], process_name) if @options[:prefix]
         
     | 
| 
       92 
112 
     | 
    
         
             
                    run process_name
         
     | 
| 
       93 
113 
     | 
    
         
             
                  end
         
     | 
| 
       94 
114 
     | 
    
         
             
                end
         
     | 
| 
       95 
115 
     | 
    
         | 
| 
       96 
     | 
    
         
            -
                def run(worker_name = nil)
         
     | 
| 
      
 116 
     | 
    
         
            +
                def run(worker_name = nil, options = {})
         
     | 
| 
       97 
117 
     | 
    
         
             
                  Dir.chdir(Rails.root)
         
     | 
| 
       98 
118 
     | 
    
         | 
| 
       99 
119 
     | 
    
         
             
                  Delayed::Worker.after_fork
         
     | 
| 
       100 
120 
     | 
    
         
             
                  Delayed::Worker.logger ||= Logger.new(File.join(Rails.root, 'log', 'delayed_job.log'))
         
     | 
| 
       101 
121 
     | 
    
         | 
| 
       102 
     | 
    
         
            -
                  worker = Delayed::Worker.new( 
     | 
| 
      
 122 
     | 
    
         
            +
                  worker = Delayed::Worker.new(options)
         
     | 
| 
       103 
123 
     | 
    
         
             
                  worker.name_prefix = "#{worker_name} "
         
     | 
| 
       104 
124 
     | 
    
         
             
                  worker.start
         
     | 
| 
       105 
125 
     | 
    
         
             
                rescue => e
         
     | 
| 
         @@ -107,5 +127,20 @@ module Delayed 
     | 
|
| 
       107 
127 
     | 
    
         
             
                  STDERR.puts e.message
         
     | 
| 
       108 
128 
     | 
    
         
             
                  exit 1
         
     | 
| 
       109 
129 
     | 
    
         
             
                end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
              private
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                def parse_worker_pool(pool)
         
     | 
| 
      
 134 
     | 
    
         
            +
                  @worker_pools ||= []
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                  queues, worker_count = pool.split(':')
         
     | 
| 
      
 137 
     | 
    
         
            +
                  if ['*', '', nil].include?(queues)
         
     | 
| 
      
 138 
     | 
    
         
            +
                    queues = []
         
     | 
| 
      
 139 
     | 
    
         
            +
                  else
         
     | 
| 
      
 140 
     | 
    
         
            +
                    queues = queues.split(',')
         
     | 
| 
      
 141 
     | 
    
         
            +
                  end
         
     | 
| 
      
 142 
     | 
    
         
            +
                  worker_count = (worker_count || 1).to_i rescue 1
         
     | 
| 
      
 143 
     | 
    
         
            +
                  @worker_pools << [queues, worker_count]
         
     | 
| 
      
 144 
     | 
    
         
            +
                end
         
     | 
| 
       110 
145 
     | 
    
         
             
              end
         
     | 
| 
       111 
146 
     | 
    
         
             
            end
         
     | 
    
        data/lib/delayed/exceptions.rb
    CHANGED
    
    | 
         @@ -3,7 +3,8 @@ require 'timeout' 
     | 
|
| 
       3 
3 
     | 
    
         
             
            module Delayed
         
     | 
| 
       4 
4 
     | 
    
         
             
              class WorkerTimeout < Timeout::Error
         
     | 
| 
       5 
5 
     | 
    
         
             
                def message
         
     | 
| 
       6 
     | 
    
         
            -
                   
     | 
| 
      
 6 
     | 
    
         
            +
                  seconds = Delayed::Worker.max_run_time.to_i
         
     | 
| 
      
 7 
     | 
    
         
            +
                  "#{super} (Delayed::Worker.max_run_time is only #{seconds} second#{seconds == 1 ? '' : 's'})"
         
     | 
| 
       7 
8 
     | 
    
         
             
                end
         
     | 
| 
       8 
9 
     | 
    
         
             
              end
         
     | 
| 
       9 
10 
     | 
    
         | 
    
        data/lib/delayed/lifecycle.rb
    CHANGED
    
    | 
         @@ -13,7 +13,9 @@ module Delayed 
     | 
|
| 
       13 
13 
     | 
    
         
             
                }
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
                def initialize
         
     | 
| 
       16 
     | 
    
         
            -
                  @callbacks = EVENTS.keys. 
     | 
| 
      
 16 
     | 
    
         
            +
                  @callbacks = EVENTS.keys.each_with_object({}) do |e, hash|
         
     | 
| 
      
 17 
     | 
    
         
            +
                    hash[e] = Callback.new
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
       17 
19 
     | 
    
         
             
                end
         
     | 
| 
       18 
20 
     | 
    
         | 
| 
       19 
21 
     | 
    
         
             
                def before(event, &block)
         
     | 
| 
         @@ -29,7 +31,7 @@ module Delayed 
     | 
|
| 
       29 
31 
     | 
    
         
             
                end
         
     | 
| 
       30 
32 
     | 
    
         | 
| 
       31 
33 
     | 
    
         
             
                def run_callbacks(event, *args, &block)
         
     | 
| 
       32 
     | 
    
         
            -
                  missing_callback(event) unless @callbacks. 
     | 
| 
      
 34 
     | 
    
         
            +
                  missing_callback(event) unless @callbacks.key?(event)
         
     | 
| 
       33 
35 
     | 
    
         | 
| 
       34 
36 
     | 
    
         
             
                  unless EVENTS[event].size == args.size
         
     | 
| 
       35 
37 
     | 
    
         
             
                    raise ArgumentError, "Callback #{event} expects #{EVENTS[event].size} parameter(s): #{EVENTS[event].join(', ')}"
         
     | 
| 
         @@ -38,17 +40,16 @@ module Delayed 
     | 
|
| 
       38 
40 
     | 
    
         
             
                  @callbacks[event].execute(*args, &block)
         
     | 
| 
       39 
41 
     | 
    
         
             
                end
         
     | 
| 
       40 
42 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                  def add(type, event, &block)
         
     | 
| 
       44 
     | 
    
         
            -
                    missing_callback(event) unless @callbacks.has_key?(event)
         
     | 
| 
      
 43 
     | 
    
         
            +
              private
         
     | 
| 
       45 
44 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
                   
     | 
| 
      
 45 
     | 
    
         
            +
                def add(type, event, &block)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  missing_callback(event) unless @callbacks.key?(event)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @callbacks[event].add(type, &block)
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
       48 
49 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
      
 50 
     | 
    
         
            +
                def missing_callback(event)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  raise InvalidCallback, "Unknown callback event: #{event}"
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
       52 
53 
     | 
    
         
             
              end
         
     | 
| 
       53 
54 
     | 
    
         | 
| 
       54 
55 
     | 
    
         
             
              class Callback
         
     | 
| 
         @@ -17,31 +17,30 @@ module Delayed 
     | 
|
| 
       17 
17 
     | 
    
         
             
                def delay(options = {})
         
     | 
| 
       18 
18 
     | 
    
         
             
                  DelayProxy.new(PerformableMethod, self, options)
         
     | 
| 
       19 
19 
     | 
    
         
             
                end
         
     | 
| 
       20 
     | 
    
         
            -
                 
     | 
| 
      
 20 
     | 
    
         
            +
                alias_method :__delay__, :delay
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
                def send_later(method, *args)
         
     | 
| 
       23 
     | 
    
         
            -
                  warn  
     | 
| 
      
 23 
     | 
    
         
            +
                  warn '[DEPRECATION] `object.send_later(:method)` is deprecated. Use `object.delay.method'
         
     | 
| 
       24 
24 
     | 
    
         
             
                  __delay__.__send__(method, *args)
         
     | 
| 
       25 
25 
     | 
    
         
             
                end
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
27 
     | 
    
         
             
                def send_at(time, method, *args)
         
     | 
| 
       28 
     | 
    
         
            -
                  warn  
     | 
| 
      
 28 
     | 
    
         
            +
                  warn '[DEPRECATION] `object.send_at(time, :method)` is deprecated. Use `object.delay(:run_at => time).method'
         
     | 
| 
       29 
29 
     | 
    
         
             
                  __delay__(:run_at => time).__send__(method, *args)
         
     | 
| 
       30 
30 
     | 
    
         
             
                end
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
       32 
32 
     | 
    
         
             
                module ClassMethods
         
     | 
| 
       33 
33 
     | 
    
         
             
                  def handle_asynchronously(method, opts = {})
         
     | 
| 
       34 
     | 
    
         
            -
                    aliased_method, punctuation = method.to_s.sub(/([?!=])$/, ''), $1
         
     | 
| 
      
 34 
     | 
    
         
            +
                    aliased_method, punctuation = method.to_s.sub(/([?!=])$/, ''), $1 # rubocop:disable PerlBackrefs
         
     | 
| 
       35 
35 
     | 
    
         
             
                    with_method, without_method = "#{aliased_method}_with_delay#{punctuation}", "#{aliased_method}_without_delay#{punctuation}"
         
     | 
| 
       36 
36 
     | 
    
         
             
                    define_method(with_method) do |*args|
         
     | 
| 
       37 
37 
     | 
    
         
             
                      curr_opts = opts.clone
         
     | 
| 
       38 
38 
     | 
    
         
             
                      curr_opts.each_key do |key|
         
     | 
| 
       39 
     | 
    
         
            -
                         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
                          end
         
     | 
| 
      
 39 
     | 
    
         
            +
                        next unless (val = curr_opts[key]).is_a?(Proc)
         
     | 
| 
      
 40 
     | 
    
         
            +
                        curr_opts[key] = if val.arity == 1
         
     | 
| 
      
 41 
     | 
    
         
            +
                          val.call(self)
         
     | 
| 
      
 42 
     | 
    
         
            +
                        else
         
     | 
| 
      
 43 
     | 
    
         
            +
                          val.call
         
     | 
| 
       45 
44 
     | 
    
         
             
                        end
         
     | 
| 
       46 
45 
     | 
    
         
             
                      end
         
     | 
| 
       47 
46 
     | 
    
         
             
                      delay(curr_opts).__send__(without_method, *args)
         
     | 
| 
         @@ -15,7 +15,7 @@ module Delayed 
     | 
|
| 
       15 
15 
     | 
    
         
             
            end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
            Mail::Message.class_eval do
         
     | 
| 
       18 
     | 
    
         
            -
              def delay(* 
     | 
| 
       19 
     | 
    
         
            -
                raise  
     | 
| 
      
 18 
     | 
    
         
            +
              def delay(*_args)
         
     | 
| 
      
 19 
     | 
    
         
            +
                raise 'Use MyMailer.delay.mailer_action(args) to delay sending of emails.'
         
     | 
| 
       20 
20 
     | 
    
         
             
              end
         
     | 
| 
       21 
21 
     | 
    
         
             
            end
         
     | 
| 
         @@ -10,7 +10,7 @@ module Delayed 
     | 
|
| 
       10 
10 
     | 
    
         
             
                  raise NoMethodError, "undefined method `#{method_name}' for #{object.inspect}" unless object.respond_to?(method_name, true)
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                  if object.respond_to?(:persisted?) && !object.persisted?
         
     | 
| 
       13 
     | 
    
         
            -
                    raise 
     | 
| 
      
 13 
     | 
    
         
            +
                    raise ArgumentError, 'Jobs cannot be created for non-persisted records'
         
     | 
| 
       14 
14 
     | 
    
         
             
                  end
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
                  self.object       = object
         
     | 
| 
         @@ -30,7 +30,7 @@ module Delayed 
     | 
|
| 
       30 
30 
     | 
    
         
             
                  object.send(symbol, *args)
         
     | 
| 
       31 
31 
     | 
    
         
             
                end
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
                def respond_to?(symbol, include_private=false)
         
     | 
| 
      
 33 
     | 
    
         
            +
                def respond_to?(symbol, include_private = false)
         
     | 
| 
       34 
34 
     | 
    
         
             
                  super || object.respond_to?(symbol, include_private)
         
     | 
| 
       35 
35 
     | 
    
         
             
                end
         
     | 
| 
       36 
36 
     | 
    
         
             
              end
         
     | 
    
        data/lib/delayed/psych_ext.rb
    CHANGED
    
    | 
         @@ -1,133 +1,69 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            if defined?(ActiveRecord)
         
     | 
| 
       2 
2 
     | 
    
         
             
              ActiveRecord::Base.class_eval do
         
     | 
| 
      
 3 
     | 
    
         
            +
                # rubocop:disable BlockNesting
         
     | 
| 
       3 
4 
     | 
    
         
             
                if instance_methods.include?(:encode_with)
         
     | 
| 
       4 
5 
     | 
    
         
             
                  def encode_with_override(coder)
         
     | 
| 
       5 
6 
     | 
    
         
             
                    encode_with_without_override(coder)
         
     | 
| 
       6 
     | 
    
         
            -
                    coder.tag = "!ruby/ActiveRecord:#{self.class.name}"
         
     | 
| 
      
 7 
     | 
    
         
            +
                    coder.tag = "!ruby/ActiveRecord:#{self.class.name}" if coder.respond_to?(:tag=)
         
     | 
| 
       7 
8 
     | 
    
         
             
                  end
         
     | 
| 
       8 
9 
     | 
    
         
             
                  alias_method :encode_with_without_override, :encode_with
         
     | 
| 
       9 
10 
     | 
    
         
             
                  alias_method :encode_with, :encode_with_override
         
     | 
| 
       10 
11 
     | 
    
         
             
                else
         
     | 
| 
       11 
12 
     | 
    
         
             
                  def encode_with(coder)
         
     | 
| 
       12 
     | 
    
         
            -
                    coder[ 
     | 
| 
       13 
     | 
    
         
            -
                    coder.tag = "!ruby/ActiveRecord:#{self.class.name}"
         
     | 
| 
      
 13 
     | 
    
         
            +
                    coder['attributes'] = attributes
         
     | 
| 
      
 14 
     | 
    
         
            +
                    coder.tag = "!ruby/ActiveRecord:#{self.class.name}" if coder.respond_to?(:tag=)
         
     | 
| 
       14 
15 
     | 
    
         
             
                  end
         
     | 
| 
       15 
16 
     | 
    
         
             
                end
         
     | 
| 
       16 
17 
     | 
    
         
             
              end
         
     | 
| 
       17 
18 
     | 
    
         
             
            end
         
     | 
| 
       18 
19 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
               
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
                coder 
     | 
| 
       23 
     | 
    
         
            -
                   
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
      
 20 
     | 
    
         
            +
            module Delayed
         
     | 
| 
      
 21 
     | 
    
         
            +
              class PerformableMethod
         
     | 
| 
      
 22 
     | 
    
         
            +
                # serialize to YAML
         
     | 
| 
      
 23 
     | 
    
         
            +
                def encode_with(coder)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  coder.map = {
         
     | 
| 
      
 25 
     | 
    
         
            +
                    'object' => object,
         
     | 
| 
      
 26 
     | 
    
         
            +
                    'method_name' => method_name,
         
     | 
| 
      
 27 
     | 
    
         
            +
                    'args' => args
         
     | 
| 
      
 28 
     | 
    
         
            +
                  }
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
       27 
30 
     | 
    
         
             
              end
         
     | 
| 
       28 
31 
     | 
    
         
             
            end
         
     | 
| 
       29 
32 
     | 
    
         | 
| 
       30 
33 
     | 
    
         
             
            module Psych
         
     | 
| 
       31 
34 
     | 
    
         
             
              module Visitors
         
     | 
| 
       32 
     | 
    
         
            -
                class YAMLTree
         
     | 
| 
       33 
     | 
    
         
            -
                  def visit_Class(klass)
         
     | 
| 
       34 
     | 
    
         
            -
                    @emitter.scalar klass.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED
         
     | 
| 
       35 
     | 
    
         
            -
                  end
         
     | 
| 
       36 
     | 
    
         
            -
                end
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
35 
     | 
    
         
             
                class ToRuby
         
     | 
| 
       39 
     | 
    
         
            -
                  def  
     | 
| 
       40 
     | 
    
         
            -
                    @st[o.anchor] = o.value if o.anchor
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                    if klass = Psych.load_tags[o.tag]
         
     | 
| 
       43 
     | 
    
         
            -
                      instance = klass.allocate
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                      if instance.respond_to?(:init_with)
         
     | 
| 
       46 
     | 
    
         
            -
                        coder = Psych::Coder.new(o.tag)
         
     | 
| 
       47 
     | 
    
         
            -
                        coder.scalar = o.value
         
     | 
| 
       48 
     | 
    
         
            -
                        instance.init_with coder
         
     | 
| 
       49 
     | 
    
         
            -
                      end
         
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
                      return instance
         
     | 
| 
       52 
     | 
    
         
            -
                    end
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
                    return o.value if o.quoted
         
     | 
| 
       55 
     | 
    
         
            -
                    return @ss.tokenize(o.value) unless o.tag
         
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
                    case o.tag
         
     | 
| 
       58 
     | 
    
         
            -
                    when '!binary', 'tag:yaml.org,2002:binary'
         
     | 
| 
       59 
     | 
    
         
            -
                      o.value.unpack('m').first
         
     | 
| 
       60 
     | 
    
         
            -
                    when '!str', 'tag:yaml.org,2002:str'
         
     | 
| 
       61 
     | 
    
         
            -
                      o.value
         
     | 
| 
       62 
     | 
    
         
            -
                    when "!ruby/object:DateTime"
         
     | 
| 
       63 
     | 
    
         
            -
                      require 'date'
         
     | 
| 
       64 
     | 
    
         
            -
                      @ss.parse_time(o.value).to_datetime
         
     | 
| 
       65 
     | 
    
         
            -
                    when "!ruby/object:Complex"
         
     | 
| 
       66 
     | 
    
         
            -
                      Complex(o.value)
         
     | 
| 
       67 
     | 
    
         
            -
                    when "!ruby/object:Rational"
         
     | 
| 
       68 
     | 
    
         
            -
                      Rational(o.value)
         
     | 
| 
       69 
     | 
    
         
            -
                    when "!ruby/class", "!ruby/module"
         
     | 
| 
       70 
     | 
    
         
            -
                      resolve_class o.value
         
     | 
| 
       71 
     | 
    
         
            -
                    when "tag:yaml.org,2002:float", "!float"
         
     | 
| 
       72 
     | 
    
         
            -
                      Float(@ss.tokenize(o.value))
         
     | 
| 
       73 
     | 
    
         
            -
                    when "!ruby/regexp"
         
     | 
| 
       74 
     | 
    
         
            -
                      o.value =~ /^\/(.*)\/([mixn]*)$/
         
     | 
| 
       75 
     | 
    
         
            -
                      source  = $1
         
     | 
| 
       76 
     | 
    
         
            -
                      options = 0
         
     | 
| 
       77 
     | 
    
         
            -
                      lang    = nil
         
     | 
| 
       78 
     | 
    
         
            -
                      ($2 || '').split('').each do |option|
         
     | 
| 
       79 
     | 
    
         
            -
                        case option
         
     | 
| 
       80 
     | 
    
         
            -
                        when 'x' then options |= Regexp::EXTENDED
         
     | 
| 
       81 
     | 
    
         
            -
                        when 'i' then options |= Regexp::IGNORECASE
         
     | 
| 
       82 
     | 
    
         
            -
                        when 'm' then options |= Regexp::MULTILINE
         
     | 
| 
       83 
     | 
    
         
            -
                        when 'n' then options |= Regexp::NOENCODING
         
     | 
| 
       84 
     | 
    
         
            -
                        else lang = option
         
     | 
| 
       85 
     | 
    
         
            -
                        end
         
     | 
| 
       86 
     | 
    
         
            -
                      end
         
     | 
| 
       87 
     | 
    
         
            -
                      Regexp.new(*[source, options, lang].compact)
         
     | 
| 
       88 
     | 
    
         
            -
                    when "!ruby/range"
         
     | 
| 
       89 
     | 
    
         
            -
                      args = o.value.split(/([.]{2,3})/, 2).map { |s|
         
     | 
| 
       90 
     | 
    
         
            -
                        accept Nodes::Scalar.new(s)
         
     | 
| 
       91 
     | 
    
         
            -
                      }
         
     | 
| 
       92 
     | 
    
         
            -
                      args.push(args.delete_at(1) == '...')
         
     | 
| 
       93 
     | 
    
         
            -
                      Range.new(*args)
         
     | 
| 
       94 
     | 
    
         
            -
                    when /^!ruby\/sym(bol)?:?(.*)?$/
         
     | 
| 
       95 
     | 
    
         
            -
                      o.value.to_sym
         
     | 
| 
       96 
     | 
    
         
            -
                    else
         
     | 
| 
       97 
     | 
    
         
            -
                      @ss.tokenize o.value
         
     | 
| 
       98 
     | 
    
         
            -
                    end
         
     | 
| 
       99 
     | 
    
         
            -
                  end
         
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
                  def visit_Psych_Nodes_Mapping_with_class(object)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  def visit_Psych_Nodes_Mapping_with_class(object) # rubocop:disable CyclomaticComplexity, MethodName
         
     | 
| 
       102 
37 
     | 
    
         
             
                    return revive(Psych.load_tags[object.tag], object) if Psych.load_tags[object.tag]
         
     | 
| 
       103 
38 
     | 
    
         | 
| 
       104 
39 
     | 
    
         
             
                    case object.tag
         
     | 
| 
       105 
40 
     | 
    
         
             
                    when /^!ruby\/ActiveRecord:(.+)$/
         
     | 
| 
       106 
     | 
    
         
            -
                      klass = resolve_class( 
     | 
| 
      
 41 
     | 
    
         
            +
                      klass = resolve_class(Regexp.last_match[1])
         
     | 
| 
       107 
42 
     | 
    
         
             
                      payload = Hash[*object.children.map { |c| accept c }]
         
     | 
| 
       108 
     | 
    
         
            -
                      id = payload[ 
     | 
| 
      
 43 
     | 
    
         
            +
                      id = payload['attributes'][klass.primary_key]
         
     | 
| 
       109 
44 
     | 
    
         
             
                      begin
         
     | 
| 
       110 
45 
     | 
    
         
             
                        klass.unscoped.find(id)
         
     | 
| 
       111 
     | 
    
         
            -
                      rescue ActiveRecord::RecordNotFound
         
     | 
| 
       112 
     | 
    
         
            -
                        raise Delayed::DeserializationError
         
     | 
| 
      
 46 
     | 
    
         
            +
                      rescue ActiveRecord::RecordNotFound => error
         
     | 
| 
      
 47 
     | 
    
         
            +
                        raise Delayed::DeserializationError, "ActiveRecord::RecordNotFound, class: #{klass}, primary key: #{id} (#{error.message})"
         
     | 
| 
       113 
48 
     | 
    
         
             
                      end
         
     | 
| 
       114 
49 
     | 
    
         
             
                    when /^!ruby\/Mongoid:(.+)$/
         
     | 
| 
       115 
     | 
    
         
            -
                      klass = resolve_class( 
     | 
| 
      
 50 
     | 
    
         
            +
                      klass = resolve_class(Regexp.last_match[1])
         
     | 
| 
       116 
51 
     | 
    
         
             
                      payload = Hash[*object.children.map { |c| accept c }]
         
     | 
| 
      
 52 
     | 
    
         
            +
                      id = payload['attributes']['_id']
         
     | 
| 
       117 
53 
     | 
    
         
             
                      begin
         
     | 
| 
       118 
     | 
    
         
            -
                        klass.find( 
     | 
| 
       119 
     | 
    
         
            -
                      rescue Mongoid::Errors::DocumentNotFound
         
     | 
| 
       120 
     | 
    
         
            -
                        raise Delayed::DeserializationError
         
     | 
| 
      
 54 
     | 
    
         
            +
                        klass.find(id)
         
     | 
| 
      
 55 
     | 
    
         
            +
                      rescue Mongoid::Errors::DocumentNotFound => error
         
     | 
| 
      
 56 
     | 
    
         
            +
                        raise Delayed::DeserializationError, "Mongoid::Errors::DocumentNotFound, class: #{klass}, primary key: #{id} (#{error.message})"
         
     | 
| 
       121 
57 
     | 
    
         
             
                      end
         
     | 
| 
       122 
58 
     | 
    
         
             
                    when /^!ruby\/DataMapper:(.+)$/
         
     | 
| 
       123 
     | 
    
         
            -
                      klass = resolve_class( 
     | 
| 
      
 59 
     | 
    
         
            +
                      klass = resolve_class(Regexp.last_match[1])
         
     | 
| 
       124 
60 
     | 
    
         
             
                      payload = Hash[*object.children.map { |c| accept c }]
         
     | 
| 
       125 
61 
     | 
    
         
             
                      begin
         
     | 
| 
       126 
     | 
    
         
            -
                        primary_keys = klass.properties.select 
     | 
| 
      
 62 
     | 
    
         
            +
                        primary_keys = klass.properties.select(&:key?)
         
     | 
| 
       127 
63 
     | 
    
         
             
                        key_names = primary_keys.map { |p| p.name.to_s }
         
     | 
| 
       128 
     | 
    
         
            -
                        klass.get!(*key_names.map { |k| payload[ 
     | 
| 
       129 
     | 
    
         
            -
                      rescue DataMapper::ObjectNotFoundError
         
     | 
| 
       130 
     | 
    
         
            -
                        raise Delayed::DeserializationError
         
     | 
| 
      
 64 
     | 
    
         
            +
                        klass.get!(*key_names.map { |k| payload['attributes'][k] })
         
     | 
| 
      
 65 
     | 
    
         
            +
                      rescue DataMapper::ObjectNotFoundError => error
         
     | 
| 
      
 66 
     | 
    
         
            +
                        raise Delayed::DeserializationError, "DataMapper::ObjectNotFoundError, class: #{klass} (#{error.message})"
         
     | 
| 
       131 
67 
     | 
    
         
             
                      end
         
     | 
| 
       132 
68 
     | 
    
         
             
                    else
         
     | 
| 
       133 
69 
     | 
    
         
             
                      visit_Psych_Nodes_Mapping_without_class(object)
         
     |