sidekiq 6.2.2 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sidekiq might be problematic. Click here for more details.

Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +279 -11
  3. data/LICENSE.txt +9 -0
  4. data/README.md +45 -32
  5. data/bin/sidekiq +4 -9
  6. data/bin/sidekiqload +207 -117
  7. data/bin/sidekiqmon +4 -1
  8. data/lib/generators/sidekiq/job_generator.rb +57 -0
  9. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
  10. data/lib/generators/sidekiq/templates/{worker_spec.rb.erb → job_spec.rb.erb} +1 -1
  11. data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
  12. data/lib/sidekiq/api.rb +331 -187
  13. data/lib/sidekiq/capsule.rb +127 -0
  14. data/lib/sidekiq/cli.rb +94 -81
  15. data/lib/sidekiq/client.rb +100 -96
  16. data/lib/sidekiq/{util.rb → component.rb} +14 -41
  17. data/lib/sidekiq/config.rb +274 -0
  18. data/lib/sidekiq/deploy.rb +62 -0
  19. data/lib/sidekiq/embedded.rb +61 -0
  20. data/lib/sidekiq/fetch.rb +26 -26
  21. data/lib/sidekiq/job.rb +371 -5
  22. data/lib/sidekiq/job_logger.rb +16 -28
  23. data/lib/sidekiq/job_retry.rb +85 -59
  24. data/lib/sidekiq/job_util.rb +105 -0
  25. data/lib/sidekiq/launcher.rb +106 -94
  26. data/lib/sidekiq/logger.rb +9 -44
  27. data/lib/sidekiq/manager.rb +40 -41
  28. data/lib/sidekiq/metrics/query.rb +153 -0
  29. data/lib/sidekiq/metrics/shared.rb +95 -0
  30. data/lib/sidekiq/metrics/tracking.rb +136 -0
  31. data/lib/sidekiq/middleware/chain.rb +96 -51
  32. data/lib/sidekiq/middleware/current_attributes.rb +56 -0
  33. data/lib/sidekiq/middleware/i18n.rb +6 -4
  34. data/lib/sidekiq/middleware/modules.rb +21 -0
  35. data/lib/sidekiq/monitor.rb +17 -4
  36. data/lib/sidekiq/paginator.rb +17 -9
  37. data/lib/sidekiq/processor.rb +60 -60
  38. data/lib/sidekiq/rails.rb +25 -6
  39. data/lib/sidekiq/redis_client_adapter.rb +96 -0
  40. data/lib/sidekiq/redis_connection.rb +17 -88
  41. data/lib/sidekiq/ring_buffer.rb +29 -0
  42. data/lib/sidekiq/scheduled.rb +101 -44
  43. data/lib/sidekiq/testing/inline.rb +4 -4
  44. data/lib/sidekiq/testing.rb +41 -68
  45. data/lib/sidekiq/transaction_aware_client.rb +44 -0
  46. data/lib/sidekiq/version.rb +2 -1
  47. data/lib/sidekiq/web/action.rb +3 -3
  48. data/lib/sidekiq/web/application.rb +47 -13
  49. data/lib/sidekiq/web/csrf_protection.rb +3 -3
  50. data/lib/sidekiq/web/helpers.rb +36 -33
  51. data/lib/sidekiq/web.rb +10 -17
  52. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  53. data/lib/sidekiq.rb +86 -201
  54. data/sidekiq.gemspec +12 -10
  55. data/web/assets/javascripts/application.js +131 -60
  56. data/web/assets/javascripts/base-charts.js +106 -0
  57. data/web/assets/javascripts/chart.min.js +13 -0
  58. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  59. data/web/assets/javascripts/dashboard-charts.js +166 -0
  60. data/web/assets/javascripts/dashboard.js +36 -273
  61. data/web/assets/javascripts/metrics.js +264 -0
  62. data/web/assets/stylesheets/application-dark.css +23 -23
  63. data/web/assets/stylesheets/application-rtl.css +2 -95
  64. data/web/assets/stylesheets/application.css +73 -402
  65. data/web/locales/ar.yml +70 -70
  66. data/web/locales/cs.yml +62 -62
  67. data/web/locales/da.yml +60 -53
  68. data/web/locales/de.yml +65 -65
  69. data/web/locales/el.yml +43 -24
  70. data/web/locales/en.yml +82 -69
  71. data/web/locales/es.yml +68 -68
  72. data/web/locales/fa.yml +65 -65
  73. data/web/locales/fr.yml +81 -67
  74. data/web/locales/gd.yml +99 -0
  75. data/web/locales/he.yml +65 -64
  76. data/web/locales/hi.yml +59 -59
  77. data/web/locales/it.yml +53 -53
  78. data/web/locales/ja.yml +73 -68
  79. data/web/locales/ko.yml +52 -52
  80. data/web/locales/lt.yml +66 -66
  81. data/web/locales/nb.yml +61 -61
  82. data/web/locales/nl.yml +52 -52
  83. data/web/locales/pl.yml +45 -45
  84. data/web/locales/pt-br.yml +63 -55
  85. data/web/locales/pt.yml +51 -51
  86. data/web/locales/ru.yml +67 -66
  87. data/web/locales/sv.yml +53 -53
  88. data/web/locales/ta.yml +60 -60
  89. data/web/locales/uk.yml +62 -61
  90. data/web/locales/ur.yml +64 -64
  91. data/web/locales/vi.yml +67 -67
  92. data/web/locales/zh-cn.yml +43 -16
  93. data/web/locales/zh-tw.yml +42 -8
  94. data/web/views/_footer.erb +6 -3
  95. data/web/views/_job_info.erb +18 -2
  96. data/web/views/_metrics_period_select.erb +12 -0
  97. data/web/views/_nav.erb +1 -1
  98. data/web/views/_paging.erb +2 -0
  99. data/web/views/_poll_link.erb +3 -6
  100. data/web/views/_summary.erb +7 -7
  101. data/web/views/busy.erb +44 -28
  102. data/web/views/dashboard.erb +44 -12
  103. data/web/views/layout.erb +1 -1
  104. data/web/views/metrics.erb +82 -0
  105. data/web/views/metrics_for_job.erb +68 -0
  106. data/web/views/morgue.erb +5 -9
  107. data/web/views/queue.erb +24 -24
  108. data/web/views/queues.erb +4 -2
  109. data/web/views/retries.erb +5 -9
  110. data/web/views/scheduled.erb +12 -13
  111. metadata +62 -31
  112. data/LICENSE +0 -9
  113. data/lib/generators/sidekiq/worker_generator.rb +0 -57
  114. data/lib/sidekiq/delay.rb +0 -41
  115. data/lib/sidekiq/exception_handler.rb +0 -27
  116. data/lib/sidekiq/extensions/action_mailer.rb +0 -48
  117. data/lib/sidekiq/extensions/active_record.rb +0 -43
  118. data/lib/sidekiq/extensions/class_methods.rb +0 -43
  119. data/lib/sidekiq/extensions/generic_proxy.rb +0 -33
  120. data/lib/sidekiq/worker.rb +0 -244
@@ -0,0 +1,274 @@
1
+ require "forwardable"
2
+
3
+ require "set"
4
+ require "sidekiq/redis_connection"
5
+
6
+ module Sidekiq
7
+ # Sidekiq::Config represents the global configuration for an instance of Sidekiq.
8
+ class Config
9
+ extend Forwardable
10
+
11
+ DEFAULTS = {
12
+ labels: Set.new,
13
+ require: ".",
14
+ environment: nil,
15
+ concurrency: 5,
16
+ timeout: 25,
17
+ poll_interval_average: nil,
18
+ average_scheduled_poll_interval: 5,
19
+ on_complex_arguments: :raise,
20
+ error_handlers: [],
21
+ death_handlers: [],
22
+ lifecycle_events: {
23
+ startup: [],
24
+ quiet: [],
25
+ shutdown: [],
26
+ # triggers when we fire the first heartbeat on startup OR repairing a network partition
27
+ heartbeat: [],
28
+ # triggers on EVERY heartbeat call, every 10 seconds
29
+ beat: []
30
+ },
31
+ dead_max_jobs: 10_000,
32
+ dead_timeout_in_seconds: 180 * 24 * 60 * 60, # 6 months
33
+ reloader: proc { |&block| block.call },
34
+ backtrace_cleaner: ->(backtrace) { backtrace }
35
+ }
36
+
37
+ ERROR_HANDLER = ->(ex, ctx) {
38
+ cfg = ctx[:_config] || Sidekiq.default_configuration
39
+ l = cfg.logger
40
+ l.warn(Sidekiq.dump_json(ctx)) unless ctx.empty?
41
+ l.warn("#{ex.class.name}: #{ex.message}")
42
+ unless ex.backtrace.nil?
43
+ backtrace = cfg[:backtrace_cleaner].call(ex.backtrace)
44
+ l.warn(backtrace.join("\n"))
45
+ end
46
+ }
47
+
48
+ def initialize(options = {})
49
+ @options = DEFAULTS.merge(options)
50
+ @options[:error_handlers] << ERROR_HANDLER if @options[:error_handlers].empty?
51
+ @directory = {}
52
+ @redis_config = {}
53
+ @capsules = {}
54
+ end
55
+
56
+ def_delegators :@options, :[], :[]=, :fetch, :key?, :has_key?, :merge!
57
+ attr_reader :capsules
58
+
59
+ # LEGACY: edits the default capsule
60
+ # config.concurrency = 5
61
+ def concurrency=(val)
62
+ default_capsule.concurrency = Integer(val)
63
+ end
64
+
65
+ def concurrency
66
+ default_capsule.concurrency
67
+ end
68
+
69
+ def total_concurrency
70
+ capsules.each_value.sum(&:concurrency)
71
+ end
72
+
73
+ # Edit the default capsule.
74
+ # config.queues = %w( high default low ) # strict
75
+ # config.queues = %w( high,3 default,2 low,1 ) # weighted
76
+ # config.queues = %w( feature1,1 feature2,1 feature3,1 ) # random
77
+ #
78
+ # With weighted priority, queue will be checked first (weight / total) of the time.
79
+ # high will be checked first (3/6) or 50% of the time.
80
+ # I'd recommend setting weights between 1-10. Weights in the hundreds or thousands
81
+ # are ridiculous and unnecessarily expensive. You can get random queue ordering
82
+ # by explicitly setting all weights to 1.
83
+ def queues=(val)
84
+ default_capsule.queues = val
85
+ end
86
+
87
+ def queues
88
+ default_capsule.queues
89
+ end
90
+
91
+ def client_middleware
92
+ @client_chain ||= Sidekiq::Middleware::Chain.new(self)
93
+ yield @client_chain if block_given?
94
+ @client_chain
95
+ end
96
+
97
+ def server_middleware
98
+ @server_chain ||= Sidekiq::Middleware::Chain.new(self)
99
+ yield @server_chain if block_given?
100
+ @server_chain
101
+ end
102
+
103
+ def default_capsule(&block)
104
+ capsule("default", &block)
105
+ end
106
+
107
+ # register a new queue processing subsystem
108
+ def capsule(name)
109
+ nm = name.to_s
110
+ cap = @capsules.fetch(nm) do
111
+ cap = Sidekiq::Capsule.new(nm, self)
112
+ @capsules[nm] = cap
113
+ end
114
+ yield cap if block_given?
115
+ cap
116
+ end
117
+
118
+ # All capsules must use the same Redis configuration
119
+ def redis=(hash)
120
+ @redis_config = @redis_config.merge(hash)
121
+ end
122
+
123
+ def redis_pool
124
+ Thread.current[:sidekiq_redis_pool] || Thread.current[:sidekiq_capsule]&.redis_pool || local_redis_pool
125
+ end
126
+
127
+ private def local_redis_pool
128
+ # this is our internal client/housekeeping pool. each capsule has its
129
+ # own pool for executing threads.
130
+ @redis ||= new_redis_pool(5, "internal")
131
+ end
132
+
133
+ def new_redis_pool(size, name = "unset")
134
+ # connection pool is lazy, it will not create connections unless you actually need them
135
+ # so don't be skimpy!
136
+ RedisConnection.create({size: size, logger: logger, pool_name: name}.merge(@redis_config))
137
+ end
138
+
139
+ def redis_info
140
+ redis do |conn|
141
+ conn.call("INFO") { |i| i.lines(chomp: true).map { |l| l.split(":", 2) }.select { |l| l.size == 2 }.to_h }
142
+ rescue RedisClientAdapter::CommandError => ex
143
+ # 2850 return fake version when INFO command has (probably) been renamed
144
+ raise unless /unknown command/.match?(ex.message)
145
+ {
146
+ "redis_version" => "9.9.9",
147
+ "uptime_in_days" => "9999",
148
+ "connected_clients" => "9999",
149
+ "used_memory_human" => "9P",
150
+ "used_memory_peak_human" => "9P"
151
+ }.freeze
152
+ end
153
+ end
154
+
155
+ def redis
156
+ raise ArgumentError, "requires a block" unless block_given?
157
+ redis_pool.with do |conn|
158
+ retryable = true
159
+ begin
160
+ yield conn
161
+ rescue RedisClientAdapter::BaseError => ex
162
+ # 2550 Failover can cause the server to become a replica, need
163
+ # to disconnect and reopen the socket to get back to the primary.
164
+ # 4495 Use the same logic if we have a "Not enough replicas" error from the primary
165
+ # 4985 Use the same logic when a blocking command is force-unblocked
166
+ # The same retry logic is also used in client.rb
167
+ if retryable && ex.message =~ /READONLY|NOREPLICAS|UNBLOCKED/
168
+ conn.close
169
+ retryable = false
170
+ retry
171
+ end
172
+ raise
173
+ end
174
+ end
175
+ end
176
+
177
+ # register global singletons which can be accessed elsewhere
178
+ def register(name, instance)
179
+ @directory[name] = instance
180
+ end
181
+
182
+ # find a singleton
183
+ def lookup(name, default_class = nil)
184
+ # JNDI is just a fancy name for a hash lookup
185
+ @directory.fetch(name) do |key|
186
+ return nil unless default_class
187
+ @directory[key] = default_class.new(self)
188
+ end
189
+ end
190
+
191
+ ##
192
+ # Death handlers are called when all retries for a job have been exhausted and
193
+ # the job dies. It's the notification to your application
194
+ # that this job will not succeed without manual intervention.
195
+ #
196
+ # Sidekiq.configure_server do |config|
197
+ # config.death_handlers << ->(job, ex) do
198
+ # end
199
+ # end
200
+ def death_handlers
201
+ @options[:death_handlers]
202
+ end
203
+
204
+ # How frequently Redis should be checked by a random Sidekiq process for
205
+ # scheduled and retriable jobs. Each individual process will take turns by
206
+ # waiting some multiple of this value.
207
+ #
208
+ # See sidekiq/scheduled.rb for an in-depth explanation of this value
209
+ def average_scheduled_poll_interval=(interval)
210
+ @options[:average_scheduled_poll_interval] = interval
211
+ end
212
+
213
+ # Register a proc to handle any error which occurs within the Sidekiq process.
214
+ #
215
+ # Sidekiq.configure_server do |config|
216
+ # config.error_handlers << proc {|ex,ctx_hash| MyErrorService.notify(ex, ctx_hash) }
217
+ # end
218
+ #
219
+ # The default error handler logs errors to @logger.
220
+ def error_handlers
221
+ @options[:error_handlers]
222
+ end
223
+
224
+ # Register a block to run at a point in the Sidekiq lifecycle.
225
+ # :startup, :quiet or :shutdown are valid events.
226
+ #
227
+ # Sidekiq.configure_server do |config|
228
+ # config.on(:shutdown) do
229
+ # puts "Goodbye cruel world!"
230
+ # end
231
+ # end
232
+ def on(event, &block)
233
+ raise ArgumentError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
234
+ raise ArgumentError, "Invalid event name: #{event}" unless @options[:lifecycle_events].key?(event)
235
+ @options[:lifecycle_events][event] << block
236
+ end
237
+
238
+ def logger
239
+ @logger ||= Sidekiq::Logger.new($stdout, level: :info).tap do |log|
240
+ log.level = Logger::INFO
241
+ log.formatter = if ENV["DYNO"]
242
+ Sidekiq::Logger::Formatters::WithoutTimestamp.new
243
+ else
244
+ Sidekiq::Logger::Formatters::Pretty.new
245
+ end
246
+ end
247
+ end
248
+
249
+ def logger=(logger)
250
+ if logger.nil?
251
+ self.logger.level = Logger::FATAL
252
+ return
253
+ end
254
+
255
+ @logger = logger
256
+ end
257
+
258
+ # INTERNAL USE ONLY
259
+ def handle_exception(ex, ctx = {})
260
+ if @options[:error_handlers].size == 0
261
+ p ["!!!!!", ex]
262
+ end
263
+ ctx[:_config] = self
264
+ @options[:error_handlers].each do |handler|
265
+ handler.call(ex, ctx)
266
+ rescue => e
267
+ l = logger
268
+ l.error "!!! ERROR HANDLER THREW AN ERROR !!!"
269
+ l.error e
270
+ l.error e.backtrace.join("\n") unless e.backtrace.nil?
271
+ end
272
+ end
273
+ end
274
+ end
@@ -0,0 +1,62 @@
1
+ require "sidekiq/redis_connection"
2
+ require "time"
3
+
4
+ # This file is designed to be required within the user's
5
+ # deployment script; it should need a bare minimum of dependencies.
6
+ # Usage:
7
+ #
8
+ # require "sidekiq/deploy"
9
+ # Sidekiq::Deploy.mark!("Some change")
10
+ #
11
+ # If you do not pass a label, Sidekiq will try to use the latest
12
+ # git commit info.
13
+ #
14
+
15
+ module Sidekiq
16
+ class Deploy
17
+ MARK_TTL = 90 * 24 * 60 * 60 # 90 days
18
+
19
+ LABEL_MAKER = -> {
20
+ `git log -1 --format="%h %s"`.strip
21
+ }
22
+
23
+ def self.mark!(label = nil)
24
+ Sidekiq::Deploy.new.mark!(label: label)
25
+ end
26
+
27
+ def initialize(pool = Sidekiq::RedisConnection.create)
28
+ @pool = pool
29
+ end
30
+
31
+ def mark!(at: Time.now, label: nil)
32
+ label ||= LABEL_MAKER.call
33
+ # we need to round the timestamp so that we gracefully
34
+ # handle an very common error in marking deploys:
35
+ # having every process mark its deploy, leading
36
+ # to N marks for each deploy. Instead we round the time
37
+ # to the minute so that multple marks within that minute
38
+ # will all naturally rollup into one mark per minute.
39
+ whence = at.utc
40
+ floor = Time.utc(whence.year, whence.month, whence.mday, whence.hour, whence.min, 0)
41
+ datecode = floor.strftime("%Y%m%d")
42
+ key = "#{datecode}-marks"
43
+ stamp = floor.iso8601
44
+
45
+ @pool.with do |c|
46
+ # only allow one deploy mark for a given label for the next minute
47
+ lock = c.set("deploylock-#{label}", stamp, nx: true, ex: 60)
48
+ if lock
49
+ c.multi do |pipe|
50
+ pipe.hsetnx(key, stamp, label)
51
+ pipe.expire(key, MARK_TTL)
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ def fetch(date = Time.now.utc.to_date)
58
+ datecode = date.strftime("%Y%m%d")
59
+ @pool.with { |c| c.hgetall("#{datecode}-marks") }
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,61 @@
1
+ require "sidekiq/component"
2
+ require "sidekiq/launcher"
3
+ require "sidekiq/metrics/tracking"
4
+
5
+ module Sidekiq
6
+ class Embedded
7
+ include Sidekiq::Component
8
+
9
+ def initialize(config)
10
+ @config = config
11
+ end
12
+
13
+ def run
14
+ housekeeping
15
+ fire_event(:startup, reverse: false, reraise: true)
16
+ @launcher = Sidekiq::Launcher.new(@config, embedded: true)
17
+ @launcher.run
18
+ sleep 0.2 # pause to give threads time to spin up
19
+
20
+ logger.info "Sidekiq running embedded, total process thread count: #{Thread.list.size}"
21
+ logger.debug { Thread.list.map(&:name) }
22
+ end
23
+
24
+ def quiet
25
+ @launcher&.quiet
26
+ end
27
+
28
+ def stop
29
+ @launcher&.stop
30
+ end
31
+
32
+ private
33
+
34
+ def housekeeping
35
+ logger.info "Running in #{RUBY_DESCRIPTION}"
36
+ logger.info Sidekiq::LICENSE
37
+ logger.info "Upgrade to Sidekiq Pro for more features and support: https://sidekiq.org" unless defined?(::Sidekiq::Pro)
38
+
39
+ # touch the connection pool so it is created before we
40
+ # fire startup and start multithreading.
41
+ info = config.redis_info
42
+ ver = Gem::Version.new(info["redis_version"])
43
+ raise "You are connecting to Redis #{ver}, Sidekiq requires Redis 6.2.0 or greater" if ver < Gem::Version.new("6.2.0")
44
+
45
+ maxmemory_policy = info["maxmemory_policy"]
46
+ if maxmemory_policy != "noeviction"
47
+ logger.warn <<~EOM
48
+
49
+
50
+ WARNING: Your Redis instance will evict Sidekiq data under heavy load.
51
+ The 'noeviction' maxmemory policy is recommended (current policy: '#{maxmemory_policy}').
52
+ See: https://github.com/sidekiq/sidekiq/wiki/Using-Redis#memory
53
+
54
+ EOM
55
+ end
56
+
57
+ logger.debug { "Client Middleware: #{@config.default_capsule.client_middleware.map(&:klass).join(", ")}" }
58
+ logger.debug { "Server Middleware: #{@config.default_capsule.server_middleware.map(&:klass).join(", ")}" }
59
+ end
60
+ end
61
+ end
data/lib/sidekiq/fetch.rb CHANGED
@@ -1,14 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "sidekiq"
4
+ require "sidekiq/component"
5
+ require "sidekiq/capsule"
4
6
 
5
- module Sidekiq
7
+ module Sidekiq # :nodoc:
6
8
  class BasicFetch
9
+ include Sidekiq::Component
7
10
  # We want the fetch operation to timeout every few seconds so the thread
8
11
  # can check if the process is shutting down.
9
12
  TIMEOUT = 2
10
13
 
11
- UnitOfWork = Struct.new(:queue, :job) {
14
+ UnitOfWork = Struct.new(:queue, :job, :config) {
12
15
  def acknowledge
13
16
  # nothing to do
14
17
  end
@@ -18,56 +21,53 @@ module Sidekiq
18
21
  end
19
22
 
20
23
  def requeue
21
- Sidekiq.redis do |conn|
24
+ config.redis do |conn|
22
25
  conn.rpush(queue, job)
23
26
  end
24
27
  end
25
28
  }
26
29
 
27
- def initialize(options)
28
- raise ArgumentError, "missing queue list" unless options[:queues]
29
- @options = options
30
- @strictly_ordered_queues = !!@options[:strict]
31
- @queues = @options[:queues].map { |q| "queue:#{q}" }
32
- if @strictly_ordered_queues
33
- @queues.uniq!
34
- @queues << TIMEOUT
35
- end
30
+ def initialize(cap)
31
+ raise ArgumentError, "missing queue list" unless cap.queues
32
+ @config = cap
33
+ @strictly_ordered_queues = cap.mode == :strict
34
+ @queues = config.queues.map { |q| "queue:#{q}" }
35
+ @queues.uniq! if @strictly_ordered_queues
36
36
  end
37
37
 
38
38
  def retrieve_work
39
39
  qs = queues_cmd
40
40
  # 4825 Sidekiq Pro with all queues paused will return an
41
- # empty set of queues with a trailing TIMEOUT value.
42
- if qs.size <= 1
41
+ # empty set of queues
42
+ if qs.size <= 0
43
43
  sleep(TIMEOUT)
44
44
  return nil
45
45
  end
46
46
 
47
- work = Sidekiq.redis { |conn| conn.brpop(*qs) }
48
- UnitOfWork.new(*work) if work
47
+ queue, job = redis { |conn| conn.blocking_call(conn.read_timeout + TIMEOUT, "brpop", *qs, TIMEOUT) }
48
+ UnitOfWork.new(queue, job, config) if queue
49
49
  end
50
50
 
51
- def bulk_requeue(inprogress, options)
51
+ def bulk_requeue(inprogress)
52
52
  return if inprogress.empty?
53
53
 
54
- Sidekiq.logger.debug { "Re-queueing terminated jobs" }
54
+ logger.debug { "Re-queueing terminated jobs" }
55
55
  jobs_to_requeue = {}
56
56
  inprogress.each do |unit_of_work|
57
57
  jobs_to_requeue[unit_of_work.queue] ||= []
58
58
  jobs_to_requeue[unit_of_work.queue] << unit_of_work.job
59
59
  end
60
60
 
61
- Sidekiq.redis do |conn|
62
- conn.pipelined do
61
+ redis do |conn|
62
+ conn.pipelined do |pipeline|
63
63
  jobs_to_requeue.each do |queue, jobs|
64
- conn.rpush(queue, jobs)
64
+ pipeline.rpush(queue, jobs)
65
65
  end
66
66
  end
67
67
  end
68
- Sidekiq.logger.info("Pushed #{inprogress.size} jobs back to Redis")
68
+ logger.info("Pushed #{inprogress.size} jobs back to Redis")
69
69
  rescue => ex
70
- Sidekiq.logger.warn("Failed to requeue #{inprogress.size} jobs: #{ex.message}")
70
+ logger.warn("Failed to requeue #{inprogress.size} jobs: #{ex.message}")
71
71
  end
72
72
 
73
73
  # Creating the Redis#brpop command takes into account any
@@ -79,9 +79,9 @@ module Sidekiq
79
79
  if @strictly_ordered_queues
80
80
  @queues
81
81
  else
82
- queues = @queues.shuffle!.uniq
83
- queues << TIMEOUT
84
- queues
82
+ permute = @queues.shuffle
83
+ permute.uniq!
84
+ permute
85
85
  end
86
86
  end
87
87
  end