sidekiq 6.4.0 → 6.5.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +50 -1
  3. data/README.md +6 -1
  4. data/bin/sidekiq +3 -3
  5. data/bin/sidekiqload +70 -66
  6. data/bin/sidekiqmon +1 -1
  7. data/lib/sidekiq/api.rb +78 -65
  8. data/lib/sidekiq/cli.rb +46 -37
  9. data/lib/sidekiq/client.rb +42 -28
  10. data/lib/sidekiq/component.rb +64 -0
  11. data/lib/sidekiq/delay.rb +1 -1
  12. data/lib/sidekiq/extensions/action_mailer.rb +2 -2
  13. data/lib/sidekiq/extensions/active_record.rb +2 -2
  14. data/lib/sidekiq/extensions/class_methods.rb +2 -2
  15. data/lib/sidekiq/extensions/generic_proxy.rb +3 -3
  16. data/lib/sidekiq/fetch.rb +17 -15
  17. data/lib/sidekiq/job_logger.rb +15 -27
  18. data/lib/sidekiq/job_retry.rb +27 -26
  19. data/lib/sidekiq/job_util.rb +15 -9
  20. data/lib/sidekiq/launcher.rb +54 -52
  21. data/lib/sidekiq/logger.rb +8 -18
  22. data/lib/sidekiq/manager.rb +28 -25
  23. data/lib/sidekiq/middleware/chain.rb +22 -13
  24. data/lib/sidekiq/middleware/current_attributes.rb +4 -0
  25. data/lib/sidekiq/middleware/i18n.rb +6 -4
  26. data/lib/sidekiq/middleware/modules.rb +19 -0
  27. data/lib/sidekiq/monitor.rb +1 -1
  28. data/lib/sidekiq/paginator.rb +8 -8
  29. data/lib/sidekiq/processor.rb +38 -38
  30. data/lib/sidekiq/rails.rb +15 -8
  31. data/lib/sidekiq/redis_client_adapter.rb +154 -0
  32. data/lib/sidekiq/redis_connection.rb +81 -48
  33. data/lib/sidekiq/ring_buffer.rb +29 -0
  34. data/lib/sidekiq/scheduled.rb +11 -10
  35. data/lib/sidekiq/testing/inline.rb +4 -4
  36. data/lib/sidekiq/testing.rb +37 -36
  37. data/lib/sidekiq/transaction_aware_client.rb +45 -0
  38. data/lib/sidekiq/version.rb +1 -1
  39. data/lib/sidekiq/web/csrf_protection.rb +2 -2
  40. data/lib/sidekiq/web/helpers.rb +5 -5
  41. data/lib/sidekiq/web.rb +3 -3
  42. data/lib/sidekiq/worker.rb +20 -17
  43. data/lib/sidekiq.rb +98 -30
  44. data/web/assets/javascripts/application.js +58 -26
  45. data/web/assets/stylesheets/application.css +1 -0
  46. data/web/locales/pt-br.yml +27 -9
  47. data/web/views/_summary.erb +1 -1
  48. data/web/views/busy.erb +3 -3
  49. metadata +8 -5
  50. data/lib/sidekiq/exception_handler.rb +0 -27
  51. data/lib/sidekiq/util.rb +0 -108
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "sidekiq/middleware/modules"
4
+
3
5
  module Sidekiq
4
6
  # Middleware is code configured to run before/after
5
7
  # a message is processed. It is patterned after Rack
@@ -44,10 +46,12 @@ module Sidekiq
44
46
  # This is an example of a minimal server middleware:
45
47
  #
46
48
  # class MyServerHook
47
- # def call(worker_instance, msg, queue)
48
- # puts "Before work"
49
+ # include Sidekiq::ServerMiddleware
50
+ # def call(job_instance, msg, queue)
51
+ # logger.info "Before job"
52
+ # redis {|conn| conn.get("foo") } # do something in Redis
49
53
  # yield
50
- # puts "After work"
54
+ # logger.info "After job"
51
55
  # end
52
56
  # end
53
57
  #
@@ -56,10 +60,11 @@ module Sidekiq
56
60
  # to Redis:
57
61
  #
58
62
  # class MyClientHook
59
- # def call(worker_class, msg, queue, redis_pool)
60
- # puts "Before push"
63
+ # include Sidekiq::ClientMiddleware
64
+ # def call(job_class, msg, queue, redis_pool)
65
+ # logger.info "Before push"
61
66
  # result = yield
62
- # puts "After push"
67
+ # logger.info "After push"
63
68
  # result
64
69
  # end
65
70
  # end
@@ -76,7 +81,8 @@ module Sidekiq
76
81
  entries.each(&block)
77
82
  end
78
83
 
79
- def initialize
84
+ def initialize(config = nil)
85
+ @config = config
80
86
  @entries = nil
81
87
  yield self if block_given?
82
88
  end
@@ -91,24 +97,24 @@ module Sidekiq
91
97
 
92
98
  def add(klass, *args)
93
99
  remove(klass)
94
- entries << Entry.new(klass, *args)
100
+ entries << Entry.new(@config, klass, *args)
95
101
  end
96
102
 
97
103
  def prepend(klass, *args)
98
104
  remove(klass)
99
- entries.insert(0, Entry.new(klass, *args))
105
+ entries.insert(0, Entry.new(@config, klass, *args))
100
106
  end
101
107
 
102
108
  def insert_before(oldklass, newklass, *args)
103
109
  i = entries.index { |entry| entry.klass == newklass }
104
- new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
110
+ new_entry = i.nil? ? Entry.new(@config, newklass, *args) : entries.delete_at(i)
105
111
  i = entries.index { |entry| entry.klass == oldklass } || 0
106
112
  entries.insert(i, new_entry)
107
113
  end
108
114
 
109
115
  def insert_after(oldklass, newklass, *args)
110
116
  i = entries.index { |entry| entry.klass == newklass }
111
- new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
117
+ new_entry = i.nil? ? Entry.new(@config, newklass, *args) : entries.delete_at(i)
112
118
  i = entries.index { |entry| entry.klass == oldklass } || entries.count - 1
113
119
  entries.insert(i + 1, new_entry)
114
120
  end
@@ -149,13 +155,16 @@ module Sidekiq
149
155
  class Entry
150
156
  attr_reader :klass
151
157
 
152
- def initialize(klass, *args)
158
+ def initialize(config, klass, *args)
159
+ @config = config
153
160
  @klass = klass
154
161
  @args = args
155
162
  end
156
163
 
157
164
  def make_new
158
- @klass.new(*@args)
165
+ x = @klass.new(*@args)
166
+ x.config = @config if @config && x.respond_to?(:config=)
167
+ x
159
168
  end
160
169
  end
161
170
  end
@@ -15,6 +15,8 @@ module Sidekiq
15
15
  #
16
16
  module CurrentAttributes
17
17
  class Save
18
+ include Sidekiq::ClientMiddleware
19
+
18
20
  def initialize(cattr)
19
21
  @klass = cattr
20
22
  end
@@ -31,6 +33,8 @@ module Sidekiq
31
33
  end
32
34
 
33
35
  class Load
36
+ include Sidekiq::ServerMiddleware
37
+
34
38
  def initialize(cattr)
35
39
  @klass = cattr
36
40
  end
@@ -10,16 +10,18 @@ module Sidekiq::Middleware::I18n
10
10
  # Get the current locale and store it in the message
11
11
  # to be sent to Sidekiq.
12
12
  class Client
13
- def call(_worker, msg, _queue, _redis)
14
- msg["locale"] ||= I18n.locale
13
+ include Sidekiq::ClientMiddleware
14
+ def call(_jobclass, job, _queue, _redis)
15
+ job["locale"] ||= I18n.locale
15
16
  yield
16
17
  end
17
18
  end
18
19
 
19
20
  # Pull the msg locale out and set the current thread to use it.
20
21
  class Server
21
- def call(_worker, msg, _queue, &block)
22
- I18n.with_locale(msg.fetch("locale", I18n.default_locale), &block)
22
+ include Sidekiq::ServerMiddleware
23
+ def call(_jobclass, job, _queue, &block)
24
+ I18n.with_locale(job.fetch("locale", I18n.default_locale), &block)
23
25
  end
24
26
  end
25
27
  end
@@ -0,0 +1,19 @@
1
+ module Sidekiq
2
+ module ServerMiddleware
3
+ attr_accessor :config
4
+ def redis_pool
5
+ config.redis_pool
6
+ end
7
+
8
+ def logger
9
+ config.logger
10
+ end
11
+
12
+ def redis(&block)
13
+ config.redis(&block)
14
+ end
15
+ end
16
+
17
+ # no difference for now
18
+ ClientMiddleware = ServerMiddleware
19
+ end
@@ -17,7 +17,7 @@ class Sidekiq::Monitor
17
17
  end
18
18
  send(section)
19
19
  rescue => e
20
- puts "Couldn't get status: #{e}"
20
+ abort "Couldn't get status: #{e}"
21
21
  end
22
22
 
23
23
  def all
@@ -16,22 +16,22 @@ module Sidekiq
16
16
 
17
17
  case type
18
18
  when "zset"
19
- total_size, items = conn.multi {
20
- conn.zcard(key)
19
+ total_size, items = conn.multi { |transaction|
20
+ transaction.zcard(key)
21
21
  if rev
22
- conn.zrevrange(key, starting, ending, with_scores: true)
22
+ transaction.zrevrange(key, starting, ending, withscores: true)
23
23
  else
24
- conn.zrange(key, starting, ending, with_scores: true)
24
+ transaction.zrange(key, starting, ending, withscores: true)
25
25
  end
26
26
  }
27
27
  [current_page, total_size, items]
28
28
  when "list"
29
- total_size, items = conn.multi {
30
- conn.llen(key)
29
+ total_size, items = conn.multi { |transaction|
30
+ transaction.llen(key)
31
31
  if rev
32
- conn.lrange(key, -ending - 1, -starting - 1)
32
+ transaction.lrange(key, -ending - 1, -starting - 1)
33
33
  else
34
- conn.lrange(key, starting, ending)
34
+ transaction.lrange(key, starting, ending)
35
35
  end
36
36
  }
37
37
  items.reverse! if rev
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "sidekiq/util"
4
3
  require "sidekiq/fetch"
5
4
  require "sidekiq/job_logger"
6
5
  require "sidekiq/job_retry"
@@ -11,33 +10,34 @@ module Sidekiq
11
10
  #
12
11
  # 1. fetches a job from Redis
13
12
  # 2. executes the job
14
- # a. instantiate the Worker
13
+ # a. instantiate the job class
15
14
  # b. run the middleware chain
16
15
  # c. call #perform
17
16
  #
18
- # A Processor can exit due to shutdown (processor_stopped)
19
- # or due to an error during job execution (processor_died)
17
+ # A Processor can exit due to shutdown or due to
18
+ # an error during job execution.
20
19
  #
21
20
  # If an error occurs in the job execution, the
22
21
  # Processor calls the Manager to create a new one
23
22
  # to replace itself and exits.
24
23
  #
25
24
  class Processor
26
- include Util
25
+ include Sidekiq::Component
27
26
 
28
27
  attr_reader :thread
29
28
  attr_reader :job
30
29
 
31
- def initialize(mgr, options)
32
- @mgr = mgr
30
+ def initialize(options, &block)
31
+ @callback = block
33
32
  @down = false
34
33
  @done = false
35
34
  @job = nil
36
35
  @thread = nil
36
+ @config = options
37
37
  @strategy = options[:fetch]
38
38
  @reloader = options[:reloader] || proc { |&block| block.call }
39
39
  @job_logger = (options[:job_logger] || Sidekiq::JobLogger).new
40
- @retrier = Sidekiq::JobRetry.new
40
+ @retrier = Sidekiq::JobRetry.new(options)
41
41
  end
42
42
 
43
43
  def terminate(wait = false)
@@ -66,26 +66,26 @@ module Sidekiq
66
66
 
67
67
  def run
68
68
  process_one until @done
69
- @mgr.processor_stopped(self)
69
+ @callback.call(self)
70
70
  rescue Sidekiq::Shutdown
71
- @mgr.processor_stopped(self)
71
+ @callback.call(self)
72
72
  rescue Exception => ex
73
- @mgr.processor_died(self, ex)
73
+ @callback.call(self, ex)
74
74
  end
75
75
 
76
- def process_one
76
+ def process_one(&block)
77
77
  @job = fetch
78
78
  process(@job) if @job
79
79
  @job = nil
80
80
  end
81
81
 
82
82
  def get_one
83
- work = @strategy.retrieve_work
83
+ uow = @strategy.retrieve_work
84
84
  if @down
85
85
  logger.info { "Redis is online, #{::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - @down} sec downtime" }
86
86
  @down = nil
87
87
  end
88
- work
88
+ uow
89
89
  rescue Sidekiq::Shutdown
90
90
  rescue => ex
91
91
  handle_fetch_exception(ex)
@@ -130,10 +130,10 @@ module Sidekiq
130
130
  # Effectively this block denotes a "unit of work" to Rails.
131
131
  @reloader.call do
132
132
  klass = constantize(job_hash["class"])
133
- worker = klass.new
134
- worker.jid = job_hash["jid"]
135
- @retrier.local(worker, jobstr, queue) do
136
- yield worker
133
+ inst = klass.new
134
+ inst.jid = job_hash["jid"]
135
+ @retrier.local(inst, jobstr, queue) do
136
+ yield inst
137
137
  end
138
138
  end
139
139
  end
@@ -142,9 +142,9 @@ module Sidekiq
142
142
  end
143
143
  end
144
144
 
145
- def process(work)
146
- jobstr = work.job
147
- queue = work.queue_name
145
+ def process(uow)
146
+ jobstr = uow.job
147
+ queue = uow.queue_name
148
148
 
149
149
  # Treat malformed JSON as a special case: job goes straight to the morgue.
150
150
  job_hash = nil
@@ -154,14 +154,14 @@ module Sidekiq
154
154
  handle_exception(ex, {context: "Invalid JSON for job", jobstr: jobstr})
155
155
  # we can't notify because the job isn't a valid hash payload.
156
156
  DeadSet.new.kill(jobstr, notify_failure: false)
157
- return work.acknowledge
157
+ return uow.acknowledge
158
158
  end
159
159
 
160
160
  ack = false
161
161
  begin
162
- dispatch(job_hash, queue, jobstr) do |worker|
163
- Sidekiq.server_middleware.invoke(worker, job_hash, queue) do
164
- execute_job(worker, job_hash["args"])
162
+ dispatch(job_hash, queue, jobstr) do |inst|
163
+ @config.server_middleware.invoke(inst, job_hash, queue) do
164
+ execute_job(inst, job_hash["args"])
165
165
  end
166
166
  end
167
167
  ack = true
@@ -186,14 +186,14 @@ module Sidekiq
186
186
  if ack
187
187
  # We don't want a shutdown signal to interrupt job acknowledgment.
188
188
  Thread.handle_interrupt(Sidekiq::Shutdown => :never) do
189
- work.acknowledge
189
+ uow.acknowledge
190
190
  end
191
191
  end
192
192
  end
193
193
  end
194
194
 
195
- def execute_job(worker, cloned_args)
196
- worker.perform(*cloned_args)
195
+ def execute_job(inst, cloned_args)
196
+ inst.perform(*cloned_args)
197
197
  end
198
198
 
199
199
  # Ruby doesn't provide atomic counters out of the box so we'll
@@ -219,39 +219,39 @@ module Sidekiq
219
219
  end
220
220
 
221
221
  # jruby's Hash implementation is not threadsafe, so we wrap it in a mutex here
222
- class SharedWorkerState
222
+ class SharedWorkState
223
223
  def initialize
224
- @worker_state = {}
224
+ @work_state = {}
225
225
  @lock = Mutex.new
226
226
  end
227
227
 
228
228
  def set(tid, hash)
229
- @lock.synchronize { @worker_state[tid] = hash }
229
+ @lock.synchronize { @work_state[tid] = hash }
230
230
  end
231
231
 
232
232
  def delete(tid)
233
- @lock.synchronize { @worker_state.delete(tid) }
233
+ @lock.synchronize { @work_state.delete(tid) }
234
234
  end
235
235
 
236
236
  def dup
237
- @lock.synchronize { @worker_state.dup }
237
+ @lock.synchronize { @work_state.dup }
238
238
  end
239
239
 
240
240
  def size
241
- @lock.synchronize { @worker_state.size }
241
+ @lock.synchronize { @work_state.size }
242
242
  end
243
243
 
244
244
  def clear
245
- @lock.synchronize { @worker_state.clear }
245
+ @lock.synchronize { @work_state.clear }
246
246
  end
247
247
  end
248
248
 
249
249
  PROCESSED = Counter.new
250
250
  FAILURE = Counter.new
251
- WORKER_STATE = SharedWorkerState.new
251
+ WORK_STATE = SharedWorkState.new
252
252
 
253
253
  def stats(jobstr, queue)
254
- WORKER_STATE.set(tid, {queue: queue, payload: jobstr, run_at: Time.now.to_i})
254
+ WORK_STATE.set(tid, {queue: queue, payload: jobstr, run_at: Time.now.to_i})
255
255
 
256
256
  begin
257
257
  yield
@@ -259,7 +259,7 @@ module Sidekiq
259
259
  FAILURE.incr
260
260
  raise
261
261
  ensure
262
- WORKER_STATE.delete(tid)
262
+ WORK_STATE.delete(tid)
263
263
  PROCESSED.incr
264
264
  end
265
265
  end
data/lib/sidekiq/rails.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "sidekiq/worker"
3
+ require "sidekiq/job"
4
4
 
5
5
  module Sidekiq
6
6
  class Rails < ::Rails::Engine
@@ -33,28 +33,35 @@ module Sidekiq
33
33
  # end
34
34
  initializer "sidekiq.active_job_integration" do
35
35
  ActiveSupport.on_load(:active_job) do
36
- include ::Sidekiq::Worker::Options unless respond_to?(:sidekiq_options)
36
+ include ::Sidekiq::Job::Options unless respond_to?(:sidekiq_options)
37
37
  end
38
38
  end
39
39
 
40
40
  initializer "sidekiq.rails_logger" do
41
- Sidekiq.configure_server do |_|
42
- # This is the integration code necessary so that if code uses `Rails.logger.info "Hello"`,
41
+ Sidekiq.configure_server do |config|
42
+ # This is the integration code necessary so that if a job uses `Rails.logger.info "Hello"`,
43
43
  # it will appear in the Sidekiq console with all of the job context. See #5021 and
44
44
  # https://github.com/rails/rails/blob/b5f2b550f69a99336482739000c58e4e04e033aa/railties/lib/rails/commands/server/server_command.rb#L82-L84
45
- unless ::Rails.logger == ::Sidekiq.logger || ::ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, $stdout)
46
- ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(::Sidekiq.logger))
45
+ unless ::Rails.logger == config.logger || ::ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, $stdout)
46
+ ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
47
47
  end
48
48
  end
49
49
  end
50
50
 
51
+ config.before_configuration do
52
+ dep = ActiveSupport::Deprecation.new("7.0", "Sidekiq")
53
+ dep.deprecate_methods(Sidekiq.singleton_class,
54
+ default_worker_options: :default_job_options,
55
+ "default_worker_options=": :default_job_options=)
56
+ end
57
+
51
58
  # This hook happens after all initializers are run, just before returning
52
59
  # from config/environment.rb back to sidekiq/cli.rb.
53
60
  #
54
61
  # None of this matters on the client-side, only within the Sidekiq process itself.
55
62
  config.after_initialize do
56
- Sidekiq.configure_server do |_|
57
- Sidekiq.options[:reloader] = Sidekiq::Rails::Reloader.new
63
+ Sidekiq.configure_server do |config|
64
+ config[:reloader] = Sidekiq::Rails::Reloader.new
58
65
  end
59
66
  end
60
67
  end
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "connection_pool"
4
+ require "redis_client"
5
+ require "redis_client/decorator"
6
+ require "uri"
7
+
8
+ module Sidekiq
9
+ class RedisClientAdapter
10
+ BaseError = RedisClient::Error
11
+ CommandError = RedisClient::CommandError
12
+
13
+ module CompatMethods
14
+ def info
15
+ @client.call("INFO") { |i| i.lines(chomp: true).map { |l| l.split(":", 2) }.select { |l| l.size == 2 }.to_h }
16
+ end
17
+
18
+ def evalsha(sha, keys, argv)
19
+ @client.call("EVALSHA", sha, keys.size, *keys, *argv)
20
+ end
21
+
22
+ def brpoplpush(*args)
23
+ @client.blocking_call(false, "BRPOPLPUSH", *args)
24
+ end
25
+
26
+ def brpop(*args)
27
+ @client.blocking_call(false, "BRPOP", *args)
28
+ end
29
+
30
+ def set(*args)
31
+ @client.call("SET", *args) { |r| r == "OK" }
32
+ end
33
+ ruby2_keywords :set if respond_to?(:ruby2_keywords, true)
34
+
35
+ def sismember(*args)
36
+ @client.call("SISMEMBER", *args) { |c| c > 0 }
37
+ end
38
+
39
+ def exists?(key)
40
+ @client.call("EXISTS", key) { |c| c > 0 }
41
+ end
42
+
43
+ private
44
+
45
+ def method_missing(*args, &block)
46
+ @client.call(*args, *block)
47
+ end
48
+ ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
49
+
50
+ def respond_to_missing?(name, include_private = false)
51
+ super # Appease the linter. We can't tell what is a valid command.
52
+ end
53
+ end
54
+
55
+ CompatClient = RedisClient::Decorator.create(CompatMethods)
56
+
57
+ class CompatClient
58
+ %i[scan sscan zscan hscan].each do |method|
59
+ alias_method :"#{method}_each", method
60
+ undef_method method
61
+ end
62
+
63
+ def disconnect!
64
+ @client.close
65
+ end
66
+
67
+ def connection
68
+ {id: @client.id}
69
+ end
70
+
71
+ def redis
72
+ self
73
+ end
74
+
75
+ def _client
76
+ @client
77
+ end
78
+
79
+ def message
80
+ yield nil, @queue.pop
81
+ end
82
+
83
+ # NB: this method does not return
84
+ def subscribe(chan)
85
+ @queue = ::Queue.new
86
+
87
+ pubsub = @client.pubsub
88
+ pubsub.call("subscribe", chan)
89
+
90
+ loop do
91
+ evt = pubsub.next_event
92
+ next if evt.nil?
93
+ next unless evt[0] == "message" && evt[1] == chan
94
+
95
+ (_, _, msg) = evt
96
+ @queue << msg
97
+ yield self
98
+ end
99
+ end
100
+ end
101
+
102
+ def initialize(options)
103
+ opts = client_opts(options)
104
+ @config = if opts.key?(:sentinels)
105
+ RedisClient.sentinel(**opts)
106
+ else
107
+ RedisClient.config(**opts)
108
+ end
109
+ end
110
+
111
+ def new_client
112
+ CompatClient.new(@config.new_client)
113
+ end
114
+
115
+ private
116
+
117
+ def client_opts(options)
118
+ opts = options.dup
119
+
120
+ if opts[:namespace]
121
+ Sidekiq.logger.error("Your Redis configuration uses the namespace '#{opts[:namespace]}' but this feature isn't supported by redis-client. " \
122
+ "Either use the redis adapter or remove the namespace.")
123
+ Kernel.exit(-127)
124
+ end
125
+
126
+ opts.delete(:size)
127
+ opts.delete(:pool_timeout)
128
+
129
+ if opts[:network_timeout]
130
+ opts[:timeout] = opts[:network_timeout]
131
+ opts.delete(:network_timeout)
132
+ end
133
+
134
+ if opts[:driver]
135
+ opts[:driver] = opts[:driver].to_sym
136
+ end
137
+
138
+ opts[:name] = opts.delete(:master_name) if opts.key?(:master_name)
139
+ opts[:role] = opts[:role].to_sym if opts.key?(:role)
140
+ opts.delete(:url) if opts.key?(:sentinels)
141
+
142
+ # Issue #3303, redis-rb will silently retry an operation.
143
+ # This can lead to duplicate jobs if Sidekiq::Client's LPUSH
144
+ # is performed twice but I believe this is much, much rarer
145
+ # than the reconnect silently fixing a problem; we keep it
146
+ # on by default.
147
+ opts[:reconnect_attempts] ||= 1
148
+
149
+ opts
150
+ end
151
+ end
152
+ end
153
+
154
+ Sidekiq::RedisConnection.adapter = Sidekiq::RedisClientAdapter