sidekiq 5.2.8 → 6.0.0
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.
Potentially problematic release.
This version of sidekiq might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +0 -2
- data/.standard.yml +20 -0
- data/6.0-Upgrade.md +70 -0
- data/Changes.md +31 -3
- data/Ent-2.0-Upgrade.md +37 -0
- data/Ent-Changes.md +12 -0
- data/Gemfile +12 -11
- data/Gemfile.lock +196 -0
- data/Pro-5.0-Upgrade.md +25 -0
- data/Pro-Changes.md +12 -3
- data/README.md +16 -30
- data/Rakefile +5 -4
- data/bin/sidekiqload +26 -22
- data/bin/sidekiqmon +9 -0
- data/lib/generators/sidekiq/templates/worker_test.rb.erb +1 -1
- data/lib/generators/sidekiq/worker_generator.rb +12 -14
- data/lib/sidekiq/api.rb +138 -151
- data/lib/sidekiq/cli.rb +97 -162
- data/lib/sidekiq/client.rb +45 -46
- data/lib/sidekiq/delay.rb +5 -6
- data/lib/sidekiq/exception_handler.rb +10 -12
- data/lib/sidekiq/extensions/action_mailer.rb +10 -20
- data/lib/sidekiq/extensions/active_record.rb +9 -7
- data/lib/sidekiq/extensions/class_methods.rb +9 -7
- data/lib/sidekiq/extensions/generic_proxy.rb +4 -4
- data/lib/sidekiq/fetch.rb +5 -6
- data/lib/sidekiq/job_logger.rb +37 -7
- data/lib/sidekiq/job_retry.rb +45 -58
- data/lib/sidekiq/launcher.rb +59 -51
- data/lib/sidekiq/logger.rb +69 -0
- data/lib/sidekiq/manager.rb +7 -9
- data/lib/sidekiq/middleware/chain.rb +3 -2
- data/lib/sidekiq/middleware/i18n.rb +5 -7
- data/lib/sidekiq/monitor.rb +148 -0
- data/lib/sidekiq/paginator.rb +11 -12
- data/lib/sidekiq/processor.rb +52 -49
- data/lib/sidekiq/rails.rb +23 -29
- data/lib/sidekiq/redis_connection.rb +31 -37
- data/lib/sidekiq/scheduled.rb +17 -19
- data/lib/sidekiq/testing/inline.rb +2 -1
- data/lib/sidekiq/testing.rb +22 -23
- data/lib/sidekiq/util.rb +17 -14
- data/lib/sidekiq/version.rb +2 -1
- data/lib/sidekiq/web/action.rb +14 -10
- data/lib/sidekiq/web/application.rb +60 -57
- data/lib/sidekiq/web/helpers.rb +66 -67
- data/lib/sidekiq/web/router.rb +17 -14
- data/lib/sidekiq/web.rb +41 -49
- data/lib/sidekiq/worker.rb +124 -97
- data/lib/sidekiq.rb +53 -42
- data/sidekiq.gemspec +16 -16
- data/web/assets/javascripts/dashboard.js +2 -21
- data/web/locales/ja.yml +2 -1
- metadata +21 -31
- data/.travis.yml +0 -11
- data/bin/sidekiqctl +0 -20
- data/lib/sidekiq/core_ext.rb +0 -1
- data/lib/sidekiq/ctl.rb +0 -221
- data/lib/sidekiq/logging.rb +0 -122
- data/lib/sidekiq/middleware/server/active_record.rb +0 -23
    
        data/lib/sidekiq/web.rb
    CHANGED
    
    | @@ -1,20 +1,21 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            -
            require 'erb'
         | 
| 3 2 |  | 
| 4 | 
            -
            require  | 
| 5 | 
            -
            require 'sidekiq/api'
         | 
| 6 | 
            -
            require 'sidekiq/paginator'
         | 
| 7 | 
            -
            require 'sidekiq/web/helpers'
         | 
| 3 | 
            +
            require "erb"
         | 
| 8 4 |  | 
| 9 | 
            -
            require  | 
| 10 | 
            -
            require  | 
| 11 | 
            -
            require  | 
| 5 | 
            +
            require "sidekiq"
         | 
| 6 | 
            +
            require "sidekiq/api"
         | 
| 7 | 
            +
            require "sidekiq/paginator"
         | 
| 8 | 
            +
            require "sidekiq/web/helpers"
         | 
| 12 9 |  | 
| 13 | 
            -
            require  | 
| 10 | 
            +
            require "sidekiq/web/router"
         | 
| 11 | 
            +
            require "sidekiq/web/action"
         | 
| 12 | 
            +
            require "sidekiq/web/application"
         | 
| 14 13 |  | 
| 15 | 
            -
            require  | 
| 16 | 
            -
             | 
| 17 | 
            -
            require  | 
| 14 | 
            +
            require "rack/protection"
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            require "rack/builder"
         | 
| 17 | 
            +
            require "rack/file"
         | 
| 18 | 
            +
            require "rack/session/cookie"
         | 
| 18 19 |  | 
| 19 20 | 
             
            module Sidekiq
         | 
| 20 21 | 
             
              class Web
         | 
| @@ -25,12 +26,12 @@ module Sidekiq | |
| 25 26 | 
             
                ASSETS = "#{ROOT}/assets"
         | 
| 26 27 |  | 
| 27 28 | 
             
                DEFAULT_TABS = {
         | 
| 28 | 
            -
                  "Dashboard" =>  | 
| 29 | 
            -
                  "Busy" | 
| 30 | 
            -
                  "Queues" | 
| 31 | 
            -
                  "Retries" | 
| 32 | 
            -
                  "Scheduled" =>  | 
| 33 | 
            -
                  "Dead" | 
| 29 | 
            +
                  "Dashboard" => "",
         | 
| 30 | 
            +
                  "Busy" => "busy",
         | 
| 31 | 
            +
                  "Queues" => "queues",
         | 
| 32 | 
            +
                  "Retries" => "retries",
         | 
| 33 | 
            +
                  "Scheduled" => "scheduled",
         | 
| 34 | 
            +
                  "Dead" => "morgue",
         | 
| 34 35 | 
             
                }
         | 
| 35 36 |  | 
| 36 37 | 
             
                class << self
         | 
| @@ -64,11 +65,11 @@ module Sidekiq | |
| 64 65 | 
             
                  end
         | 
| 65 66 |  | 
| 66 67 | 
             
                  def enable(*opts)
         | 
| 67 | 
            -
                    opts.each {|key| set(key, true) }
         | 
| 68 | 
            +
                    opts.each { |key| set(key, true) }
         | 
| 68 69 | 
             
                  end
         | 
| 69 70 |  | 
| 70 71 | 
             
                  def disable(*opts)
         | 
| 71 | 
            -
                    opts.each {|key| set(key, false) }
         | 
| 72 | 
            +
                    opts.each { |key| set(key, false) }
         | 
| 72 73 | 
             
                  end
         | 
| 73 74 |  | 
| 74 75 | 
             
                  # Helper for the Sinatra syntax: Sidekiq::Web.set(:session_secret, Rails.application.secrets...)
         | 
| @@ -81,10 +82,10 @@ module Sidekiq | |
| 81 82 | 
             
                end
         | 
| 82 83 |  | 
| 83 84 | 
             
                def self.inherited(child)
         | 
| 84 | 
            -
                  child.app_url =  | 
| 85 | 
            -
                  child.session_secret =  | 
| 86 | 
            -
                  child.redis_pool =  | 
| 87 | 
            -
                  child.sessions =  | 
| 85 | 
            +
                  child.app_url = app_url
         | 
| 86 | 
            +
                  child.session_secret = session_secret
         | 
| 87 | 
            +
                  child.redis_pool = redis_pool
         | 
| 88 | 
            +
                  child.sessions = sessions
         | 
| 88 89 | 
             
                end
         | 
| 89 90 |  | 
| 90 91 | 
             
                def settings
         | 
| @@ -113,11 +114,11 @@ module Sidekiq | |
| 113 114 | 
             
                end
         | 
| 114 115 |  | 
| 115 116 | 
             
                def enable(*opts)
         | 
| 116 | 
            -
                  opts.each {|key| set(key, true) }
         | 
| 117 | 
            +
                  opts.each { |key| set(key, true) }
         | 
| 117 118 | 
             
                end
         | 
| 118 119 |  | 
| 119 120 | 
             
                def disable(*opts)
         | 
| 120 | 
            -
                  opts.each {|key| set(key, false) }
         | 
| 121 | 
            +
                  opts.each { |key| set(key, false) }
         | 
| 121 122 | 
             
                end
         | 
| 122 123 |  | 
| 123 124 | 
             
                def set(attribute, value)
         | 
| @@ -145,28 +146,28 @@ module Sidekiq | |
| 145 146 | 
             
                private
         | 
| 146 147 |  | 
| 147 148 | 
             
                def using?(middleware)
         | 
| 148 | 
            -
                  middlewares.any? do |(m,_)|
         | 
| 149 | 
            -
                    m. | 
| 149 | 
            +
                  middlewares.any? do |(m, _)|
         | 
| 150 | 
            +
                    m.is_a?(Array) && (m[0] == middleware || m[0].is_a?(middleware))
         | 
| 150 151 | 
             
                  end
         | 
| 151 152 | 
             
                end
         | 
| 152 153 |  | 
| 153 154 | 
             
                def build_sessions
         | 
| 154 155 | 
             
                  middlewares = self.middlewares
         | 
| 155 156 |  | 
| 156 | 
            -
                  unless using?(::Rack::Protection) || ENV[ | 
| 157 | 
            -
                    middlewares.unshift [[::Rack::Protection, { | 
| 157 | 
            +
                  unless using?(::Rack::Protection) || ENV["RACK_ENV"] == "test"
         | 
| 158 | 
            +
                    middlewares.unshift [[::Rack::Protection, {use: :authenticity_token}], nil]
         | 
| 158 159 | 
             
                  end
         | 
| 159 160 |  | 
| 160 161 | 
             
                  s = sessions
         | 
| 161 162 | 
             
                  return unless s
         | 
| 162 163 |  | 
| 163 164 | 
             
                  unless using? ::Rack::Session::Cookie
         | 
| 164 | 
            -
                    unless secret = Web.session_secret
         | 
| 165 | 
            -
                      require  | 
| 165 | 
            +
                    unless (secret = Web.session_secret)
         | 
| 166 | 
            +
                      require "securerandom"
         | 
| 166 167 | 
             
                      secret = SecureRandom.hex(64)
         | 
| 167 168 | 
             
                    end
         | 
| 168 169 |  | 
| 169 | 
            -
                    options = { | 
| 170 | 
            +
                    options = {secret: secret}
         | 
| 170 171 | 
             
                    options = options.merge(s.to_hash) if s.respond_to? :to_hash
         | 
| 171 172 |  | 
| 172 173 | 
             
                    middlewares.unshift [[::Rack::Session::Cookie, options], nil]
         | 
| @@ -180,13 +181,13 @@ module Sidekiq | |
| 180 181 | 
             
                  klass = self.class
         | 
| 181 182 |  | 
| 182 183 | 
             
                  ::Rack::Builder.new do
         | 
| 183 | 
            -
                    %w | 
| 184 | 
            +
                    %w[stylesheets javascripts images].each do |asset_dir|
         | 
| 184 185 | 
             
                      map "/#{asset_dir}" do
         | 
| 185 | 
            -
                        run ::Rack::File.new("#{ASSETS}/#{asset_dir}", { | 
| 186 | 
            +
                        run ::Rack::File.new("#{ASSETS}/#{asset_dir}", {"Cache-Control" => "public, max-age=86400"})
         | 
| 186 187 | 
             
                      end
         | 
| 187 188 | 
             
                    end
         | 
| 188 189 |  | 
| 189 | 
            -
                    middlewares.each {|middleware, block| use(*middleware, &block) }
         | 
| 190 | 
            +
                    middlewares.each { |middleware, block| use(*middleware, &block) }
         | 
| 190 191 |  | 
| 191 192 | 
             
                    run WebApplication.new(klass)
         | 
| 192 193 | 
             
                  end
         | 
| @@ -196,18 +197,9 @@ module Sidekiq | |
| 196 197 | 
             
              Sidekiq::WebApplication.helpers WebHelpers
         | 
| 197 198 | 
             
              Sidekiq::WebApplication.helpers Sidekiq::Paginator
         | 
| 198 199 |  | 
| 199 | 
            -
              Sidekiq::WebAction.class_eval  | 
| 200 | 
            -
             | 
| 201 | 
            -
             | 
| 202 | 
            -
            if defined?(::ActionDispatch::Request::Session) &&
         | 
| 203 | 
            -
                !::ActionDispatch::Request::Session.method_defined?(:each)
         | 
| 204 | 
            -
              # mperham/sidekiq#2460
         | 
| 205 | 
            -
              # Rack apps can't reuse the Rails session store without
         | 
| 206 | 
            -
              # this monkeypatch, fixed in Rails 5.
         | 
| 207 | 
            -
              class ActionDispatch::Request::Session
         | 
| 208 | 
            -
                def each(&block)
         | 
| 209 | 
            -
                  hash = self.to_hash
         | 
| 210 | 
            -
                  hash.each(&block)
         | 
| 200 | 
            +
              Sidekiq::WebAction.class_eval <<-RUBY, __FILE__, __LINE__ + 1
         | 
| 201 | 
            +
                def _render
         | 
| 202 | 
            +
                  #{ERB.new(File.read(Web::LAYOUT)).src}
         | 
| 211 203 | 
             
                end
         | 
| 212 | 
            -
               | 
| 204 | 
            +
              RUBY
         | 
| 213 205 | 
             
            end
         | 
    
        data/lib/sidekiq/worker.rb
    CHANGED
    
    | @@ -1,8 +1,8 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            -
            require 'sidekiq/client'
         | 
| 3 2 |  | 
| 4 | 
            -
             | 
| 3 | 
            +
            require "sidekiq/client"
         | 
| 5 4 |  | 
| 5 | 
            +
            module Sidekiq
         | 
| 6 6 | 
             
              ##
         | 
| 7 7 | 
             
              # Include this module in your worker class and you can easily create
         | 
| 8 8 | 
             
              # asynchronous jobs:
         | 
| @@ -21,15 +21,124 @@ module Sidekiq | |
| 21 21 | 
             
              #
         | 
| 22 22 | 
             
              # Note that perform_async is a class method, perform is an instance method.
         | 
| 23 23 | 
             
              module Worker
         | 
| 24 | 
            +
                ##
         | 
| 25 | 
            +
                # The Options module is extracted so we can include it in ActiveJob::Base
         | 
| 26 | 
            +
                # and allow native AJs to configure Sidekiq features/internals.
         | 
| 27 | 
            +
                module Options
         | 
| 28 | 
            +
                  def self.included(base)
         | 
| 29 | 
            +
                    base.extend(ClassMethods)
         | 
| 30 | 
            +
                    base.sidekiq_class_attribute :sidekiq_options_hash
         | 
| 31 | 
            +
                    base.sidekiq_class_attribute :sidekiq_retry_in_block
         | 
| 32 | 
            +
                    base.sidekiq_class_attribute :sidekiq_retries_exhausted_block
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  module ClassMethods
         | 
| 36 | 
            +
                    ACCESSOR_MUTEX = Mutex.new
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    ##
         | 
| 39 | 
            +
                    # Allows customization for this type of Worker.
         | 
| 40 | 
            +
                    # Legal options:
         | 
| 41 | 
            +
                    #
         | 
| 42 | 
            +
                    #   queue - name of queue to use for this job type, default *default*
         | 
| 43 | 
            +
                    #   retry - enable retries for this Worker in case of error during execution,
         | 
| 44 | 
            +
                    #      *true* to use the default or *Integer* count
         | 
| 45 | 
            +
                    #   backtrace - whether to save any error backtrace in the retry payload to display in web UI,
         | 
| 46 | 
            +
                    #      can be true, false or an integer number of lines to save, default *false*
         | 
| 47 | 
            +
                    #
         | 
| 48 | 
            +
                    # In practice, any option is allowed.  This is the main mechanism to configure the
         | 
| 49 | 
            +
                    # options for a specific job.
         | 
| 50 | 
            +
                    def sidekiq_options(opts = {})
         | 
| 51 | 
            +
                      opts = Hash[opts.map { |k, v| [k.to_s, v] }] # stringify
         | 
| 52 | 
            +
                      self.sidekiq_options_hash = get_sidekiq_options.merge(Hash[opts.map { |k, v| [k.to_s, v] }])
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                    def sidekiq_retry_in(&block)
         | 
| 56 | 
            +
                      self.sidekiq_retry_in_block = block
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    def sidekiq_retries_exhausted(&block)
         | 
| 60 | 
            +
                      self.sidekiq_retries_exhausted_block = block
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    def get_sidekiq_options # :nodoc:
         | 
| 64 | 
            +
                      self.sidekiq_options_hash ||= Sidekiq.default_worker_options
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    def sidekiq_class_attribute(*attrs)
         | 
| 68 | 
            +
                      instance_reader = true
         | 
| 69 | 
            +
                      instance_writer = true
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                      attrs.each do |name|
         | 
| 72 | 
            +
                        synchronized_getter = "__synchronized_#{name}"
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                        singleton_class.instance_eval do
         | 
| 75 | 
            +
                          undef_method(name) if method_defined?(name) || private_method_defined?(name)
         | 
| 76 | 
            +
                        end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                        define_singleton_method(synchronized_getter) { nil }
         | 
| 79 | 
            +
                        singleton_class.class_eval do
         | 
| 80 | 
            +
                          private(synchronized_getter)
         | 
| 81 | 
            +
                        end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                        define_singleton_method(name) { ACCESSOR_MUTEX.synchronize { send synchronized_getter } }
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                        ivar = "@#{name}"
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                        singleton_class.instance_eval do
         | 
| 88 | 
            +
                          m = "#{name}="
         | 
| 89 | 
            +
                          undef_method(m) if method_defined?(m) || private_method_defined?(m)
         | 
| 90 | 
            +
                        end
         | 
| 91 | 
            +
                        define_singleton_method("#{name}=") do |val|
         | 
| 92 | 
            +
                          singleton_class.class_eval do
         | 
| 93 | 
            +
                            ACCESSOR_MUTEX.synchronize do
         | 
| 94 | 
            +
                              undef_method(synchronized_getter) if method_defined?(synchronized_getter) || private_method_defined?(synchronized_getter)
         | 
| 95 | 
            +
                              define_method(synchronized_getter) { val }
         | 
| 96 | 
            +
                            end
         | 
| 97 | 
            +
                          end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                          if singleton_class?
         | 
| 100 | 
            +
                            class_eval do
         | 
| 101 | 
            +
                              undef_method(name) if method_defined?(name) || private_method_defined?(name)
         | 
| 102 | 
            +
                              define_method(name) do
         | 
| 103 | 
            +
                                if instance_variable_defined? ivar
         | 
| 104 | 
            +
                                  instance_variable_get ivar
         | 
| 105 | 
            +
                                else
         | 
| 106 | 
            +
                                  singleton_class.send name
         | 
| 107 | 
            +
                                end
         | 
| 108 | 
            +
                              end
         | 
| 109 | 
            +
                            end
         | 
| 110 | 
            +
                          end
         | 
| 111 | 
            +
                          val
         | 
| 112 | 
            +
                        end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                        if instance_reader
         | 
| 115 | 
            +
                          undef_method(name) if method_defined?(name) || private_method_defined?(name)
         | 
| 116 | 
            +
                          define_method(name) do
         | 
| 117 | 
            +
                            if instance_variable_defined?(ivar)
         | 
| 118 | 
            +
                              instance_variable_get ivar
         | 
| 119 | 
            +
                            else
         | 
| 120 | 
            +
                              self.class.public_send name
         | 
| 121 | 
            +
                            end
         | 
| 122 | 
            +
                          end
         | 
| 123 | 
            +
                        end
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                        if instance_writer
         | 
| 126 | 
            +
                          m = "#{name}="
         | 
| 127 | 
            +
                          undef_method(m) if method_defined?(m) || private_method_defined?(m)
         | 
| 128 | 
            +
                          attr_writer name
         | 
| 129 | 
            +
                        end
         | 
| 130 | 
            +
                      end
         | 
| 131 | 
            +
                    end
         | 
| 132 | 
            +
                  end
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
             | 
| 24 135 | 
             
                attr_accessor :jid
         | 
| 25 136 |  | 
| 26 137 | 
             
                def self.included(base)
         | 
| 27 | 
            -
                  raise ArgumentError, " | 
| 138 | 
            +
                  raise ArgumentError, "Sidekiq::Worker cannot be included in an ActiveJob: #{base.name}" if base.ancestors.any? { |c| c.name == "ActiveJob::Base" }
         | 
| 28 139 |  | 
| 140 | 
            +
                  base.include(Options)
         | 
| 29 141 | 
             
                  base.extend(ClassMethods)
         | 
| 30 | 
            -
                  base.sidekiq_class_attribute :sidekiq_options_hash
         | 
| 31 | 
            -
                  base.sidekiq_class_attribute :sidekiq_retry_in_block
         | 
| 32 | 
            -
                  base.sidekiq_class_attribute :sidekiq_retries_exhausted_block
         | 
| 33 142 | 
             
                end
         | 
| 34 143 |  | 
| 35 144 | 
             
                def logger
         | 
| @@ -52,7 +161,7 @@ module Sidekiq | |
| 52 161 | 
             
                  end
         | 
| 53 162 |  | 
| 54 163 | 
             
                  def perform_async(*args)
         | 
| 55 | 
            -
                    @klass.client_push(@opts.merge( | 
| 164 | 
            +
                    @klass.client_push(@opts.merge("args" => args, "class" => @klass))
         | 
| 56 165 | 
             
                  end
         | 
| 57 166 |  | 
| 58 167 | 
             
                  # +interval+ must be a timestamp, numeric or something that acts
         | 
| @@ -62,17 +171,15 @@ module Sidekiq | |
| 62 171 | 
             
                    now = Time.now.to_f
         | 
| 63 172 | 
             
                    ts = (int < 1_000_000_000 ? now + int : int)
         | 
| 64 173 |  | 
| 65 | 
            -
                    payload = @opts.merge( | 
| 174 | 
            +
                    payload = @opts.merge("class" => @klass, "args" => args, "at" => ts)
         | 
| 66 175 | 
             
                    # Optimization to enqueue something now that is scheduled to go out now or in the past
         | 
| 67 | 
            -
                    payload.delete( | 
| 176 | 
            +
                    payload.delete("at") if ts <= now
         | 
| 68 177 | 
             
                    @klass.client_push(payload)
         | 
| 69 178 | 
             
                  end
         | 
| 70 179 | 
             
                  alias_method :perform_at, :perform_in
         | 
| 71 180 | 
             
                end
         | 
| 72 181 |  | 
| 73 182 | 
             
                module ClassMethods
         | 
| 74 | 
            -
                  ACCESSOR_MUTEX = Mutex.new
         | 
| 75 | 
            -
             | 
| 76 183 | 
             
                  def delay(*args)
         | 
| 77 184 | 
             
                    raise ArgumentError, "Do not call .delay on a Sidekiq::Worker class, call .perform_async"
         | 
| 78 185 | 
             
                  end
         | 
| @@ -90,7 +197,7 @@ module Sidekiq | |
| 90 197 | 
             
                  end
         | 
| 91 198 |  | 
| 92 199 | 
             
                  def perform_async(*args)
         | 
| 93 | 
            -
                    client_push( | 
| 200 | 
            +
                    client_push("class" => self, "args" => args)
         | 
| 94 201 | 
             
                  end
         | 
| 95 202 |  | 
| 96 203 | 
             
                  # +interval+ must be a timestamp, numeric or something that acts
         | 
| @@ -100,10 +207,10 @@ module Sidekiq | |
| 100 207 | 
             
                    now = Time.now.to_f
         | 
| 101 208 | 
             
                    ts = (int < 1_000_000_000 ? now + int : int)
         | 
| 102 209 |  | 
| 103 | 
            -
                    item = { | 
| 210 | 
            +
                    item = {"class" => self, "args" => args, "at" => ts}
         | 
| 104 211 |  | 
| 105 212 | 
             
                    # Optimization to enqueue something now that is scheduled to go out now or in the past
         | 
| 106 | 
            -
                    item.delete( | 
| 213 | 
            +
                    item.delete("at") if ts <= now
         | 
| 107 214 |  | 
| 108 215 | 
             
                    client_push(item)
         | 
| 109 216 | 
             
                  end
         | 
| @@ -122,25 +229,12 @@ module Sidekiq | |
| 122 229 | 
             
                  #
         | 
| 123 230 | 
             
                  # In practice, any option is allowed.  This is the main mechanism to configure the
         | 
| 124 231 | 
             
                  # options for a specific job.
         | 
| 125 | 
            -
                  def sidekiq_options(opts={})
         | 
| 126 | 
            -
                     | 
| 127 | 
            -
                    self.sidekiq_options_hash = get_sidekiq_options.merge(Hash[opts.map{|k, v| [k.to_s, v]}])
         | 
| 128 | 
            -
                  end
         | 
| 129 | 
            -
             | 
| 130 | 
            -
                  def sidekiq_retry_in(&block)
         | 
| 131 | 
            -
                    self.sidekiq_retry_in_block = block
         | 
| 132 | 
            -
                  end
         | 
| 133 | 
            -
             | 
| 134 | 
            -
                  def sidekiq_retries_exhausted(&block)
         | 
| 135 | 
            -
                    self.sidekiq_retries_exhausted_block = block
         | 
| 136 | 
            -
                  end
         | 
| 137 | 
            -
             | 
| 138 | 
            -
                  def get_sidekiq_options # :nodoc:
         | 
| 139 | 
            -
                    self.sidekiq_options_hash ||= Sidekiq.default_worker_options
         | 
| 232 | 
            +
                  def sidekiq_options(opts = {})
         | 
| 233 | 
            +
                    super
         | 
| 140 234 | 
             
                  end
         | 
| 141 235 |  | 
| 142 236 | 
             
                  def client_push(item) # :nodoc:
         | 
| 143 | 
            -
                    pool = Thread.current[:sidekiq_via_pool] || get_sidekiq_options[ | 
| 237 | 
            +
                    pool = Thread.current[:sidekiq_via_pool] || get_sidekiq_options["pool"] || Sidekiq.redis_pool
         | 
| 144 238 | 
             
                    # stringify
         | 
| 145 239 | 
             
                    item.keys.each do |key|
         | 
| 146 240 | 
             
                      item[key.to_s] = item.delete(key)
         | 
| @@ -148,73 +242,6 @@ module Sidekiq | |
| 148 242 |  | 
| 149 243 | 
             
                    Sidekiq::Client.new(pool).push(item)
         | 
| 150 244 | 
             
                  end
         | 
| 151 | 
            -
             | 
| 152 | 
            -
                  def sidekiq_class_attribute(*attrs)
         | 
| 153 | 
            -
                    instance_reader = true
         | 
| 154 | 
            -
                    instance_writer = true
         | 
| 155 | 
            -
             | 
| 156 | 
            -
                    attrs.each do |name|
         | 
| 157 | 
            -
                      synchronized_getter = "__synchronized_#{name}"
         | 
| 158 | 
            -
             | 
| 159 | 
            -
                      singleton_class.instance_eval do
         | 
| 160 | 
            -
                        undef_method(name) if method_defined?(name) || private_method_defined?(name)
         | 
| 161 | 
            -
                      end
         | 
| 162 | 
            -
             | 
| 163 | 
            -
                      define_singleton_method(synchronized_getter) { nil }
         | 
| 164 | 
            -
                      singleton_class.class_eval do
         | 
| 165 | 
            -
                        private(synchronized_getter)
         | 
| 166 | 
            -
                      end
         | 
| 167 | 
            -
             | 
| 168 | 
            -
                      define_singleton_method(name) { ACCESSOR_MUTEX.synchronize { send synchronized_getter } }
         | 
| 169 | 
            -
             | 
| 170 | 
            -
                      ivar = "@#{name}"
         | 
| 171 | 
            -
             | 
| 172 | 
            -
                      singleton_class.instance_eval do
         | 
| 173 | 
            -
                        m = "#{name}="
         | 
| 174 | 
            -
                        undef_method(m) if method_defined?(m) || private_method_defined?(m)
         | 
| 175 | 
            -
                      end
         | 
| 176 | 
            -
                      define_singleton_method("#{name}=") do |val|
         | 
| 177 | 
            -
                        singleton_class.class_eval do
         | 
| 178 | 
            -
                          ACCESSOR_MUTEX.synchronize do
         | 
| 179 | 
            -
                            undef_method(synchronized_getter) if method_defined?(synchronized_getter) || private_method_defined?(synchronized_getter)
         | 
| 180 | 
            -
                            define_method(synchronized_getter) { val }
         | 
| 181 | 
            -
                          end
         | 
| 182 | 
            -
                        end
         | 
| 183 | 
            -
             | 
| 184 | 
            -
                        if singleton_class?
         | 
| 185 | 
            -
                          class_eval do
         | 
| 186 | 
            -
                            undef_method(name) if method_defined?(name) || private_method_defined?(name)
         | 
| 187 | 
            -
                            define_method(name) do
         | 
| 188 | 
            -
                              if instance_variable_defined? ivar
         | 
| 189 | 
            -
                                instance_variable_get ivar
         | 
| 190 | 
            -
                              else
         | 
| 191 | 
            -
                                singleton_class.send name
         | 
| 192 | 
            -
                              end
         | 
| 193 | 
            -
                            end
         | 
| 194 | 
            -
                          end
         | 
| 195 | 
            -
                        end
         | 
| 196 | 
            -
                        val
         | 
| 197 | 
            -
                      end
         | 
| 198 | 
            -
             | 
| 199 | 
            -
                      if instance_reader
         | 
| 200 | 
            -
                        undef_method(name) if method_defined?(name) || private_method_defined?(name)
         | 
| 201 | 
            -
                        define_method(name) do
         | 
| 202 | 
            -
                          if instance_variable_defined?(ivar)
         | 
| 203 | 
            -
                            instance_variable_get ivar
         | 
| 204 | 
            -
                          else
         | 
| 205 | 
            -
                            self.class.public_send name
         | 
| 206 | 
            -
                          end
         | 
| 207 | 
            -
                        end
         | 
| 208 | 
            -
                      end
         | 
| 209 | 
            -
             | 
| 210 | 
            -
                      if instance_writer
         | 
| 211 | 
            -
                        m = "#{name}="
         | 
| 212 | 
            -
                        undef_method(m) if method_defined?(m) || private_method_defined?(m)
         | 
| 213 | 
            -
                        attr_writer name
         | 
| 214 | 
            -
                      end
         | 
| 215 | 
            -
                    end
         | 
| 216 | 
            -
                  end
         | 
| 217 | 
            -
             | 
| 218 245 | 
             
                end
         | 
| 219 246 | 
             
              end
         | 
| 220 247 | 
             
            end
         | 
    
        data/lib/sidekiq.rb
    CHANGED
    
    | @@ -1,27 +1,27 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            require  | 
| 4 | 
            -
            fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2. | 
| 3 | 
            +
            require "sidekiq/version"
         | 
| 4 | 
            +
            fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.5.0." if RUBY_PLATFORM != "java" && Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.5.0")
         | 
| 5 5 |  | 
| 6 | 
            -
            require  | 
| 7 | 
            -
            require  | 
| 8 | 
            -
            require  | 
| 9 | 
            -
            require  | 
| 10 | 
            -
            require  | 
| 6 | 
            +
            require "sidekiq/logger"
         | 
| 7 | 
            +
            require "sidekiq/client"
         | 
| 8 | 
            +
            require "sidekiq/worker"
         | 
| 9 | 
            +
            require "sidekiq/redis_connection"
         | 
| 10 | 
            +
            require "sidekiq/delay"
         | 
| 11 11 |  | 
| 12 | 
            -
            require  | 
| 12 | 
            +
            require "json"
         | 
| 13 13 |  | 
| 14 14 | 
             
            module Sidekiq
         | 
| 15 | 
            -
              NAME =  | 
| 16 | 
            -
              LICENSE =  | 
| 15 | 
            +
              NAME = "Sidekiq"
         | 
| 16 | 
            +
              LICENSE = "See LICENSE and the LGPL-3.0 for licensing details."
         | 
| 17 17 |  | 
| 18 18 | 
             
              DEFAULTS = {
         | 
| 19 19 | 
             
                queues: [],
         | 
| 20 20 | 
             
                labels: [],
         | 
| 21 21 | 
             
                concurrency: 10,
         | 
| 22 | 
            -
                require:  | 
| 22 | 
            +
                require: ".",
         | 
| 23 23 | 
             
                environment: nil,
         | 
| 24 | 
            -
                timeout:  | 
| 24 | 
            +
                timeout: 25,
         | 
| 25 25 | 
             
                poll_interval_average: nil,
         | 
| 26 26 | 
             
                average_scheduled_poll_interval: 5,
         | 
| 27 27 | 
             
                error_handlers: [],
         | 
| @@ -38,8 +38,8 @@ module Sidekiq | |
| 38 38 | 
             
              }
         | 
| 39 39 |  | 
| 40 40 | 
             
              DEFAULT_WORKER_OPTIONS = {
         | 
| 41 | 
            -
                 | 
| 42 | 
            -
                 | 
| 41 | 
            +
                "retry" => true,
         | 
| 42 | 
            +
                "queue" => "default",
         | 
| 43 43 | 
             
              }
         | 
| 44 44 |  | 
| 45 45 | 
             
              FAKE_INFO = {
         | 
| @@ -47,7 +47,7 @@ module Sidekiq | |
| 47 47 | 
             
                "uptime_in_days" => "9999",
         | 
| 48 48 | 
             
                "connected_clients" => "9999",
         | 
| 49 49 | 
             
                "used_memory_human" => "9P",
         | 
| 50 | 
            -
                "used_memory_peak_human" => "9P"
         | 
| 50 | 
            +
                "used_memory_peak_human" => "9P",
         | 
| 51 51 | 
             
              }
         | 
| 52 52 |  | 
| 53 53 | 
             
              def self.❨╯°□°❩╯︵┻━┻
         | 
| @@ -96,9 +96,13 @@ module Sidekiq | |
| 96 96 | 
             
                  begin
         | 
| 97 97 | 
             
                    yield conn
         | 
| 98 98 | 
             
                  rescue Redis::CommandError => ex
         | 
| 99 | 
            -
                    #2550 Failover can cause the server to become a replica, need
         | 
| 99 | 
            +
                    # 2550 Failover can cause the server to become a replica, need
         | 
| 100 100 | 
             
                    # to disconnect and reopen the socket to get back to the primary.
         | 
| 101 | 
            -
                     | 
| 101 | 
            +
                    if retryable && ex.message =~ /READONLY/
         | 
| 102 | 
            +
                      conn.disconnect!
         | 
| 103 | 
            +
                      retryable = false
         | 
| 104 | 
            +
                      retry
         | 
| 105 | 
            +
                    end
         | 
| 102 106 | 
             
                    raise
         | 
| 103 107 | 
             
                  end
         | 
| 104 108 | 
             
                end
         | 
| @@ -106,19 +110,17 @@ module Sidekiq | |
| 106 110 |  | 
| 107 111 | 
             
              def self.redis_info
         | 
| 108 112 | 
             
                redis do |conn|
         | 
| 109 | 
            -
                   | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
                     | 
| 113 | 
            -
             | 
| 114 | 
            -
                     | 
| 115 | 
            -
                      conn.info
         | 
| 116 | 
            -
                    end
         | 
| 117 | 
            -
                  rescue Redis::CommandError => ex
         | 
| 118 | 
            -
                    #2850 return fake version when INFO command has (probably) been renamed
         | 
| 119 | 
            -
                    raise unless ex.message =~ /unknown command/
         | 
| 120 | 
            -
                    FAKE_INFO
         | 
| 113 | 
            +
                  # admin commands can't go through redis-namespace starting
         | 
| 114 | 
            +
                  # in redis-namespace 2.0
         | 
| 115 | 
            +
                  if conn.respond_to?(:namespace)
         | 
| 116 | 
            +
                    conn.redis.info
         | 
| 117 | 
            +
                  else
         | 
| 118 | 
            +
                    conn.info
         | 
| 121 119 | 
             
                  end
         | 
| 120 | 
            +
                rescue Redis::CommandError => ex
         | 
| 121 | 
            +
                  # 2850 return fake version when INFO command has (probably) been renamed
         | 
| 122 | 
            +
                  raise unless /unknown command/.match?(ex.message)
         | 
| 123 | 
            +
                  FAKE_INFO
         | 
| 122 124 | 
             
                end
         | 
| 123 125 | 
             
              end
         | 
| 124 126 |  | 
| @@ -152,18 +154,13 @@ module Sidekiq | |
| 152 154 |  | 
| 153 155 | 
             
              def self.default_worker_options=(hash)
         | 
| 154 156 | 
             
                # stringify
         | 
| 155 | 
            -
                @default_worker_options = default_worker_options.merge(Hash[hash.map{|k, v| [k.to_s, v]}])
         | 
| 157 | 
            +
                @default_worker_options = default_worker_options.merge(Hash[hash.map { |k, v| [k.to_s, v] }])
         | 
| 156 158 | 
             
              end
         | 
| 159 | 
            +
             | 
| 157 160 | 
             
              def self.default_worker_options
         | 
| 158 161 | 
             
                defined?(@default_worker_options) ? @default_worker_options : DEFAULT_WORKER_OPTIONS
         | 
| 159 162 | 
             
              end
         | 
| 160 163 |  | 
| 161 | 
            -
              def self.default_retries_exhausted=(prok)
         | 
| 162 | 
            -
                logger.info { "default_retries_exhausted is deprecated, please use `config.death_handlers << -> {|job, ex| }`" }
         | 
| 163 | 
            -
                return nil unless prok
         | 
| 164 | 
            -
                death_handlers << prok
         | 
| 165 | 
            -
              end
         | 
| 166 | 
            -
             | 
| 167 164 | 
             
              ##
         | 
| 168 165 | 
             
              # Death handlers are called when all retries for a job have been exhausted and
         | 
| 169 166 | 
             
              # the job dies.  It's the notification to your application
         | 
| @@ -180,15 +177,29 @@ module Sidekiq | |
| 180 177 | 
             
              def self.load_json(string)
         | 
| 181 178 | 
             
                JSON.parse(string)
         | 
| 182 179 | 
             
              end
         | 
| 180 | 
            +
             | 
| 183 181 | 
             
              def self.dump_json(object)
         | 
| 184 182 | 
             
                JSON.generate(object)
         | 
| 185 183 | 
             
              end
         | 
| 186 184 |  | 
| 185 | 
            +
              def self.log_formatter
         | 
| 186 | 
            +
                @log_formatter ||= if ENV["DYNO"]
         | 
| 187 | 
            +
                  Sidekiq::Logger::Formatters::WithoutTimestamp.new
         | 
| 188 | 
            +
                else
         | 
| 189 | 
            +
                  Sidekiq::Logger::Formatters::Pretty.new
         | 
| 190 | 
            +
                end
         | 
| 191 | 
            +
              end
         | 
| 192 | 
            +
             | 
| 193 | 
            +
              def self.log_formatter=(log_formatter)
         | 
| 194 | 
            +
                @log_formatter = log_formatter
         | 
| 195 | 
            +
              end
         | 
| 196 | 
            +
             | 
| 187 197 | 
             
              def self.logger
         | 
| 188 | 
            -
                Sidekiq:: | 
| 198 | 
            +
                @logger ||= Sidekiq::Logger.new(STDOUT, level: Logger::INFO)
         | 
| 189 199 | 
             
              end
         | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 200 | 
            +
             | 
| 201 | 
            +
              def self.logger=(logger)
         | 
| 202 | 
            +
                @logger = logger
         | 
| 192 203 | 
             
              end
         | 
| 193 204 |  | 
| 194 205 | 
             
              # How frequently Redis should be checked by a random Sidekiq process for
         | 
| @@ -197,7 +208,7 @@ module Sidekiq | |
| 197 208 | 
             
              #
         | 
| 198 209 | 
             
              # See sidekiq/scheduled.rb for an in-depth explanation of this value
         | 
| 199 210 | 
             
              def self.average_scheduled_poll_interval=(interval)
         | 
| 200 | 
            -
                 | 
| 211 | 
            +
                options[:average_scheduled_poll_interval] = interval
         | 
| 201 212 | 
             
              end
         | 
| 202 213 |  | 
| 203 214 | 
             
              # Register a proc to handle any error which occurs within the Sidekiq process.
         | 
| @@ -208,7 +219,7 @@ module Sidekiq | |
| 208 219 | 
             
              #
         | 
| 209 220 | 
             
              # The default error handler logs errors to Sidekiq.logger.
         | 
| 210 221 | 
             
              def self.error_handlers
         | 
| 211 | 
            -
                 | 
| 222 | 
            +
                options[:error_handlers]
         | 
| 212 223 | 
             
              end
         | 
| 213 224 |  | 
| 214 225 | 
             
              # Register a block to run at a point in the Sidekiq lifecycle.
         | 
| @@ -234,4 +245,4 @@ module Sidekiq | |
| 234 245 | 
             
              class Shutdown < Interrupt; end
         | 
| 235 246 | 
             
            end
         | 
| 236 247 |  | 
| 237 | 
            -
            require  | 
| 248 | 
            +
            require "sidekiq/rails" if defined?(::Rails::Engine)
         | 
    
        data/sidekiq.gemspec
    CHANGED
    
    | @@ -1,21 +1,21 @@ | |
| 1 | 
            -
            require_relative  | 
| 1 | 
            +
            require_relative "lib/sidekiq/version"
         | 
| 2 2 |  | 
| 3 3 | 
             
            Gem::Specification.new do |gem|
         | 
| 4 | 
            -
              gem.authors | 
| 5 | 
            -
              gem.email | 
| 6 | 
            -
              gem.summary | 
| 7 | 
            -
              gem.description | 
| 8 | 
            -
              gem.homepage | 
| 9 | 
            -
              gem.license | 
| 4 | 
            +
              gem.authors = ["Mike Perham"]
         | 
| 5 | 
            +
              gem.email = ["mperham@gmail.com"]
         | 
| 6 | 
            +
              gem.summary = "Simple, efficient background processing for Ruby"
         | 
| 7 | 
            +
              gem.description = "Simple, efficient background processing for Ruby."
         | 
| 8 | 
            +
              gem.homepage = "http://sidekiq.org"
         | 
| 9 | 
            +
              gem.license = "LGPL-3.0"
         | 
| 10 10 |  | 
| 11 | 
            -
              gem.executables | 
| 12 | 
            -
              gem.files | 
| 13 | 
            -
              gem.name | 
| 14 | 
            -
              gem.version | 
| 15 | 
            -
              gem.required_ruby_version = ">= 2. | 
| 11 | 
            +
              gem.executables = ["sidekiq"]
         | 
| 12 | 
            +
              gem.files = `git ls-files | grep -Ev '^(test|myapp|examples)'`.split("\n")
         | 
| 13 | 
            +
              gem.name = "sidekiq"
         | 
| 14 | 
            +
              gem.version = Sidekiq::VERSION
         | 
| 15 | 
            +
              gem.required_ruby_version = ">= 2.5.0"
         | 
| 16 16 |  | 
| 17 | 
            -
              gem.add_dependency  | 
| 18 | 
            -
              gem.add_dependency  | 
| 19 | 
            -
              gem.add_dependency  | 
| 20 | 
            -
              gem.add_dependency  | 
| 17 | 
            +
              gem.add_dependency "redis", ">= 4.1.0"
         | 
| 18 | 
            +
              gem.add_dependency "connection_pool", ">= 2.2.2"
         | 
| 19 | 
            +
              gem.add_dependency "rack", ">= 2.0.0"
         | 
| 20 | 
            +
              gem.add_dependency "rack-protection", ">= 2.0.0"
         | 
| 21 21 | 
             
            end
         |