sidekiq 6.5.12 → 7.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +224 -20
  3. data/README.md +43 -35
  4. data/bin/multi_queue_bench +271 -0
  5. data/bin/sidekiq +3 -8
  6. data/bin/sidekiqload +204 -118
  7. data/bin/sidekiqmon +3 -0
  8. data/lib/sidekiq/api.rb +187 -135
  9. data/lib/sidekiq/capsule.rb +127 -0
  10. data/lib/sidekiq/cli.rb +59 -75
  11. data/lib/sidekiq/client.rb +66 -37
  12. data/lib/sidekiq/component.rb +4 -1
  13. data/lib/sidekiq/config.rb +287 -0
  14. data/lib/sidekiq/deploy.rb +62 -0
  15. data/lib/sidekiq/embedded.rb +61 -0
  16. data/lib/sidekiq/fetch.rb +11 -14
  17. data/lib/sidekiq/job.rb +371 -10
  18. data/lib/sidekiq/job_logger.rb +2 -2
  19. data/lib/sidekiq/job_retry.rb +36 -18
  20. data/lib/sidekiq/job_util.rb +51 -15
  21. data/lib/sidekiq/launcher.rb +71 -65
  22. data/lib/sidekiq/logger.rb +2 -27
  23. data/lib/sidekiq/manager.rb +9 -11
  24. data/lib/sidekiq/metrics/query.rb +7 -4
  25. data/lib/sidekiq/metrics/shared.rb +8 -7
  26. data/lib/sidekiq/metrics/tracking.rb +27 -21
  27. data/lib/sidekiq/middleware/chain.rb +19 -18
  28. data/lib/sidekiq/middleware/current_attributes.rb +52 -20
  29. data/lib/sidekiq/monitor.rb +16 -3
  30. data/lib/sidekiq/paginator.rb +2 -2
  31. data/lib/sidekiq/processor.rb +46 -51
  32. data/lib/sidekiq/rails.rb +15 -10
  33. data/lib/sidekiq/redis_client_adapter.rb +23 -66
  34. data/lib/sidekiq/redis_connection.rb +15 -117
  35. data/lib/sidekiq/scheduled.rb +22 -23
  36. data/lib/sidekiq/testing.rb +32 -41
  37. data/lib/sidekiq/transaction_aware_client.rb +11 -5
  38. data/lib/sidekiq/version.rb +2 -1
  39. data/lib/sidekiq/web/action.rb +8 -3
  40. data/lib/sidekiq/web/application.rb +108 -15
  41. data/lib/sidekiq/web/csrf_protection.rb +10 -7
  42. data/lib/sidekiq/web/helpers.rb +52 -38
  43. data/lib/sidekiq/web.rb +17 -16
  44. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  45. data/lib/sidekiq.rb +76 -274
  46. data/sidekiq.gemspec +12 -10
  47. data/web/assets/javascripts/application.js +39 -0
  48. data/web/assets/javascripts/base-charts.js +106 -0
  49. data/web/assets/javascripts/dashboard-charts.js +182 -0
  50. data/web/assets/javascripts/dashboard.js +10 -232
  51. data/web/assets/javascripts/metrics.js +151 -115
  52. data/web/assets/stylesheets/application-dark.css +4 -0
  53. data/web/assets/stylesheets/application-rtl.css +10 -89
  54. data/web/assets/stylesheets/application.css +45 -298
  55. data/web/locales/ar.yml +70 -70
  56. data/web/locales/cs.yml +62 -62
  57. data/web/locales/da.yml +60 -53
  58. data/web/locales/de.yml +65 -65
  59. data/web/locales/el.yml +2 -7
  60. data/web/locales/en.yml +78 -70
  61. data/web/locales/es.yml +68 -68
  62. data/web/locales/fa.yml +65 -65
  63. data/web/locales/fr.yml +81 -67
  64. data/web/locales/gd.yml +99 -0
  65. data/web/locales/he.yml +65 -64
  66. data/web/locales/hi.yml +59 -59
  67. data/web/locales/it.yml +53 -53
  68. data/web/locales/ja.yml +67 -69
  69. data/web/locales/ko.yml +52 -52
  70. data/web/locales/lt.yml +66 -66
  71. data/web/locales/nb.yml +61 -61
  72. data/web/locales/nl.yml +52 -52
  73. data/web/locales/pl.yml +45 -45
  74. data/web/locales/pt-br.yml +79 -69
  75. data/web/locales/pt.yml +51 -51
  76. data/web/locales/ru.yml +67 -66
  77. data/web/locales/sv.yml +53 -53
  78. data/web/locales/ta.yml +60 -60
  79. data/web/locales/uk.yml +62 -61
  80. data/web/locales/ur.yml +64 -64
  81. data/web/locales/vi.yml +67 -67
  82. data/web/locales/zh-cn.yml +20 -18
  83. data/web/locales/zh-tw.yml +10 -1
  84. data/web/views/_footer.erb +17 -2
  85. data/web/views/_job_info.erb +18 -2
  86. data/web/views/_metrics_period_select.erb +12 -0
  87. data/web/views/_paging.erb +2 -0
  88. data/web/views/_poll_link.erb +1 -1
  89. data/web/views/_summary.erb +7 -7
  90. data/web/views/busy.erb +46 -35
  91. data/web/views/dashboard.erb +26 -5
  92. data/web/views/filtering.erb +7 -0
  93. data/web/views/metrics.erb +46 -24
  94. data/web/views/metrics_for_job.erb +41 -69
  95. data/web/views/morgue.erb +5 -9
  96. data/web/views/queue.erb +10 -14
  97. data/web/views/queues.erb +9 -3
  98. data/web/views/retries.erb +5 -9
  99. data/web/views/scheduled.erb +12 -13
  100. metadata +44 -38
  101. data/lib/sidekiq/delay.rb +0 -43
  102. data/lib/sidekiq/extensions/action_mailer.rb +0 -48
  103. data/lib/sidekiq/extensions/active_record.rb +0 -43
  104. data/lib/sidekiq/extensions/class_methods.rb +0 -43
  105. data/lib/sidekiq/extensions/generic_proxy.rb +0 -33
  106. data/lib/sidekiq/metrics/deploy.rb +0 -47
  107. data/lib/sidekiq/worker.rb +0 -370
  108. data/web/assets/javascripts/graph.js +0 -16
  109. /data/{LICENSE → LICENSE.txt} +0 -0
@@ -7,27 +7,31 @@ module Sidekiq
7
7
  # This can be useful for multi-tenancy, i18n locale, timezone, any implicit
8
8
  # per-request attribute. See +ActiveSupport::CurrentAttributes+.
9
9
  #
10
+ # For multiple current attributes, pass an array of current attributes.
11
+ #
10
12
  # @example
11
13
  #
12
14
  # # in your initializer
13
15
  # require "sidekiq/middleware/current_attributes"
14
16
  # Sidekiq::CurrentAttributes.persist("Myapp::Current")
17
+ # # or multiple current attributes
18
+ # Sidekiq::CurrentAttributes.persist(["Myapp::Current", "Myapp::OtherCurrent"])
15
19
  #
16
20
  module CurrentAttributes
17
21
  class Save
18
22
  include Sidekiq::ClientMiddleware
19
23
 
20
- def initialize(cattr)
21
- @strklass = cattr
24
+ def initialize(cattrs)
25
+ @cattrs = cattrs
22
26
  end
23
27
 
24
28
  def call(_, job, _, _)
25
- attrs = @strklass.constantize.attributes
26
- if attrs.any?
27
- if job.has_key?("cattr")
28
- job["cattr"].merge!(attrs)
29
- else
30
- job["cattr"] = attrs
29
+ @cattrs.each do |(key, strklass)|
30
+ if !job.has_key?(key)
31
+ attrs = strklass.constantize.attributes
32
+ # Retries can push the job N times, we don't
33
+ # want retries to reset cattr. #5692, #5090
34
+ job[key] = attrs if attrs.any?
31
35
  end
32
36
  end
33
37
  yield
@@ -37,26 +41,54 @@ module Sidekiq
37
41
  class Load
38
42
  include Sidekiq::ServerMiddleware
39
43
 
40
- def initialize(cattr)
41
- @strklass = cattr
44
+ def initialize(cattrs)
45
+ @cattrs = cattrs
42
46
  end
43
47
 
44
48
  def call(_, job, _, &block)
45
- if job.has_key?("cattr")
46
- @strklass.constantize.set(job["cattr"], &block)
47
- else
48
- yield
49
+ cattrs_to_reset = []
50
+
51
+ @cattrs.each do |(key, strklass)|
52
+ if job.has_key?(key)
53
+ constklass = strklass.constantize
54
+ cattrs_to_reset << constklass
55
+
56
+ job[key].each do |(attribute, value)|
57
+ constklass.public_send(:"#{attribute}=", value)
58
+ end
59
+ end
49
60
  end
61
+
62
+ yield
63
+ ensure
64
+ cattrs_to_reset.each(&:reset)
50
65
  end
51
66
  end
52
67
 
53
- def self.persist(klass)
54
- Sidekiq.configure_client do |config|
55
- config.client_middleware.add Save, klass.to_s
68
+ class << self
69
+ def persist(klass_or_array, config = Sidekiq.default_configuration)
70
+ cattrs = build_cattrs_hash(klass_or_array)
71
+
72
+ config.client_middleware.add Save, cattrs
73
+ config.server_middleware.add Load, cattrs
56
74
  end
57
- Sidekiq.configure_server do |config|
58
- config.client_middleware.add Save, klass.to_s
59
- config.server_middleware.add Load, klass.to_s
75
+
76
+ private
77
+
78
+ def build_cattrs_hash(klass_or_array)
79
+ if klass_or_array.is_a?(Array)
80
+ {}.tap do |hash|
81
+ klass_or_array.each_with_index do |klass, index|
82
+ hash[key_at(index)] = klass.to_s
83
+ end
84
+ end
85
+ else
86
+ {key_at(0) => klass_or_array.to_s}
87
+ end
88
+ end
89
+
90
+ def key_at(index)
91
+ (index == 0) ? "cattr" : "cattr_#{index}"
60
92
  end
61
93
  end
62
94
  end
@@ -16,8 +16,6 @@ class Sidekiq::Monitor
16
16
  return
17
17
  end
18
18
  send(section)
19
- rescue => e
20
- abort "Couldn't get status: #{e}"
21
19
  end
22
20
 
23
21
  def all
@@ -49,10 +47,25 @@ class Sidekiq::Monitor
49
47
  def processes
50
48
  puts "---- Processes (#{process_set.size}) ----"
51
49
  process_set.each_with_index do |process, index|
50
+ # Keep compatibility with legacy versions since we don't want to break sidekiqmon during rolling upgrades or downgrades.
51
+ #
52
+ # Before:
53
+ # ["default", "critical"]
54
+ #
55
+ # After:
56
+ # {"default" => 1, "critical" => 10}
57
+ queues =
58
+ if process["weights"]
59
+ process["weights"].sort_by { |queue| queue[0] }.map { |capsule| capsule.map { |name, weight| (weight > 0) ? "#{name}: #{weight}" : name }.join(", ") }
60
+ else
61
+ process["queues"].sort
62
+ end
63
+
52
64
  puts "#{process["identity"]} #{tags_for(process)}"
53
65
  puts " Started: #{Time.at(process["started_at"])} (#{time_ago(process["started_at"])})"
54
66
  puts " Threads: #{process["concurrency"]} (#{process["busy"]} busy)"
55
- puts " Queues: #{split_multiline(process["queues"].sort, pad: 11)}"
67
+ puts " Queues: #{split_multiline(queues, pad: 11)}"
68
+ puts " Version: #{process["version"] || "Unknown"}" if process["version"] != Sidekiq::VERSION
56
69
  puts "" unless (index + 1) == process_set.size
57
70
  end
58
71
  end
@@ -19,9 +19,9 @@ module Sidekiq
19
19
  total_size, items = conn.multi { |transaction|
20
20
  transaction.zcard(key)
21
21
  if rev
22
- transaction.zrevrange(key, starting, ending, withscores: true)
22
+ transaction.zrange(key, starting, ending, "REV", "withscores")
23
23
  else
24
- transaction.zrange(key, starting, ending, withscores: true)
24
+ transaction.zrange(key, starting, ending, "withscores")
25
25
  end
26
26
  }
27
27
  [current_page, total_size, items]
@@ -26,18 +26,18 @@ module Sidekiq
26
26
 
27
27
  attr_reader :thread
28
28
  attr_reader :job
29
+ attr_reader :capsule
29
30
 
30
- def initialize(options, &block)
31
+ def initialize(capsule, &block)
32
+ @config = @capsule = capsule
31
33
  @callback = block
32
34
  @down = false
33
35
  @done = false
34
36
  @job = nil
35
37
  @thread = nil
36
- @config = options
37
- @strategy = options[:fetch]
38
- @reloader = options[:reloader] || proc { |&block| block.call }
39
- @job_logger = (options[:job_logger] || Sidekiq::JobLogger).new
40
- @retrier = Sidekiq::JobRetry.new(options)
38
+ @reloader = Sidekiq.default_configuration[:reloader]
39
+ @job_logger = (capsule.config[:job_logger] || Sidekiq::JobLogger).new(logger)
40
+ @retrier = Sidekiq::JobRetry.new(capsule)
41
41
  end
42
42
 
43
43
  def terminate(wait = false)
@@ -59,12 +59,16 @@ module Sidekiq
59
59
  end
60
60
 
61
61
  def start
62
- @thread ||= safe_thread("processor", &method(:run))
62
+ @thread ||= safe_thread("#{config.name}/processor", &method(:run))
63
63
  end
64
64
 
65
65
  private unless $TESTING
66
66
 
67
67
  def run
68
+ # By setting this thread-local, Sidekiq.redis will access +Sidekiq::Capsule#redis_pool+
69
+ # instead of the global pool in +Sidekiq::Config#redis_pool+.
70
+ Thread.current[:sidekiq_capsule] = @capsule
71
+
68
72
  process_one until @done
69
73
  @callback.call(self)
70
74
  rescue Sidekiq::Shutdown
@@ -80,7 +84,7 @@ module Sidekiq
80
84
  end
81
85
 
82
86
  def get_one
83
- uow = @strategy.retrieve_work
87
+ uow = capsule.fetcher.retrieve_work
84
88
  if @down
85
89
  logger.info { "Redis is online, #{::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - @down} sec downtime" }
86
90
  @down = nil
@@ -129,7 +133,7 @@ module Sidekiq
129
133
  # the Reloader. It handles code loading, db connection management, etc.
130
134
  # Effectively this block denotes a "unit of work" to Rails.
131
135
  @reloader.call do
132
- klass = constantize(job_hash["class"])
136
+ klass = Object.const_get(job_hash["class"])
133
137
  inst = klass.new
134
138
  inst.jid = job_hash["jid"]
135
139
  @retrier.local(inst, jobstr, queue) do
@@ -142,6 +146,11 @@ module Sidekiq
142
146
  end
143
147
  end
144
148
 
149
+ IGNORE_SHUTDOWN_INTERRUPTS = {Sidekiq::Shutdown => :never}
150
+ private_constant :IGNORE_SHUTDOWN_INTERRUPTS
151
+ ALLOW_SHUTDOWN_INTERRUPTS = {Sidekiq::Shutdown => :immediate}
152
+ private_constant :ALLOW_SHUTDOWN_INTERRUPTS
153
+
145
154
  def process(uow)
146
155
  jobstr = uow.job
147
156
  queue = uow.queue_name
@@ -153,47 +162,46 @@ module Sidekiq
153
162
  rescue => ex
154
163
  handle_exception(ex, {context: "Invalid JSON for job", jobstr: jobstr})
155
164
  now = Time.now.to_f
156
- config.redis do |conn|
165
+ redis do |conn|
157
166
  conn.multi do |xa|
158
167
  xa.zadd("dead", now.to_s, jobstr)
159
- xa.zremrangebyscore("dead", "-inf", now - config[:dead_timeout_in_seconds])
160
- xa.zremrangebyrank("dead", 0, - config[:dead_max_jobs])
168
+ xa.zremrangebyscore("dead", "-inf", now - @capsule.config[:dead_timeout_in_seconds])
169
+ xa.zremrangebyrank("dead", 0, - @capsule.config[:dead_max_jobs])
161
170
  end
162
171
  end
163
172
  return uow.acknowledge
164
173
  end
165
174
 
166
175
  ack = false
167
- begin
168
- dispatch(job_hash, queue, jobstr) do |inst|
169
- @config.server_middleware.invoke(inst, job_hash, queue) do
170
- execute_job(inst, job_hash["args"])
176
+ Thread.handle_interrupt(IGNORE_SHUTDOWN_INTERRUPTS) do
177
+ Thread.handle_interrupt(ALLOW_SHUTDOWN_INTERRUPTS) do
178
+ dispatch(job_hash, queue, jobstr) do |inst|
179
+ config.server_middleware.invoke(inst, job_hash, queue) do
180
+ execute_job(inst, job_hash["args"])
181
+ end
171
182
  end
183
+ ack = true
184
+ rescue Sidekiq::Shutdown
185
+ # Had to force kill this job because it didn't finish
186
+ # within the timeout. Don't acknowledge the work since
187
+ # we didn't properly finish it.
188
+ rescue Sidekiq::JobRetry::Handled => h
189
+ # this is the common case: job raised error and Sidekiq::JobRetry::Handled
190
+ # signals that we created a retry successfully. We can acknowledge the job.
191
+ ack = true
192
+ e = h.cause || h
193
+ handle_exception(e, {context: "Job raised exception", job: job_hash})
194
+ raise e
195
+ rescue Exception => ex
196
+ # Unexpected error! This is very bad and indicates an exception that got past
197
+ # the retry subsystem (e.g. network partition). We won't acknowledge the job
198
+ # so it can be rescued when using Sidekiq Pro.
199
+ handle_exception(ex, {context: "Internal exception!", job: job_hash, jobstr: jobstr})
200
+ raise ex
172
201
  end
173
- ack = true
174
- rescue Sidekiq::Shutdown
175
- # Had to force kill this job because it didn't finish
176
- # within the timeout. Don't acknowledge the work since
177
- # we didn't properly finish it.
178
- rescue Sidekiq::JobRetry::Handled => h
179
- # this is the common case: job raised error and Sidekiq::JobRetry::Handled
180
- # signals that we created a retry successfully. We can acknowlege the job.
181
- ack = true
182
- e = h.cause || h
183
- handle_exception(e, {context: "Job raised exception", job: job_hash})
184
- raise e
185
- rescue Exception => ex
186
- # Unexpected error! This is very bad and indicates an exception that got past
187
- # the retry subsystem (e.g. network partition). We won't acknowledge the job
188
- # so it can be rescued when using Sidekiq Pro.
189
- handle_exception(ex, {context: "Internal exception!", job: job_hash, jobstr: jobstr})
190
- raise ex
191
202
  ensure
192
203
  if ack
193
- # We don't want a shutdown signal to interrupt job acknowledgment.
194
- Thread.handle_interrupt(Sidekiq::Shutdown => :never) do
195
- uow.acknowledge
196
- end
204
+ uow.acknowledge
197
205
  end
198
206
  end
199
207
  end
@@ -269,18 +277,5 @@ module Sidekiq
269
277
  PROCESSED.incr
270
278
  end
271
279
  end
272
-
273
- def constantize(str)
274
- return Object.const_get(str) unless str.include?("::")
275
-
276
- names = str.split("::")
277
- names.shift if names.empty? || names.first.empty?
278
-
279
- names.inject(Object) do |constant, name|
280
- # the false flag limits search for name to under the constant namespace
281
- # which mimics Rails' behaviour
282
- constant.const_get(name, false)
283
- end
284
- end
285
280
  end
286
281
  end
data/lib/sidekiq/rails.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "sidekiq/job"
4
+ require "rails"
4
5
 
5
6
  module Sidekiq
6
7
  class Rails < ::Rails::Engine
@@ -10,7 +11,8 @@ module Sidekiq
10
11
  end
11
12
 
12
13
  def call
13
- @app.reloader.wrap do
14
+ params = (::Rails::VERSION::STRING >= "7.1") ? {source: "job.sidekiq"} : {}
15
+ @app.reloader.wrap(**params) do
14
16
  yield
15
17
  end
16
18
  end
@@ -18,11 +20,15 @@ module Sidekiq
18
20
  def inspect
19
21
  "#<Sidekiq::Rails::Reloader @app=#{@app.class.name}>"
20
22
  end
23
+
24
+ def to_hash
25
+ {app: @app.class.name}
26
+ end
21
27
  end
22
28
 
23
29
  # By including the Options module, we allow AJs to directly control sidekiq features
24
30
  # via the *sidekiq_options* class method and, for instance, not use AJ's retry system.
25
- # AJ retries don't show up in the Sidekiq UI Retries tab, save any error data, can't be
31
+ # AJ retries don't show up in the Sidekiq UI Retries tab, don't save any error data, can't be
26
32
  # manually retried, don't automatically die, etc.
27
33
  #
28
34
  # class SomeJob < ActiveJob::Base
@@ -37,11 +43,10 @@ module Sidekiq
37
43
  end
38
44
  end
39
45
 
40
- config.before_configuration do
41
- dep = ActiveSupport::Deprecation.new("7.0", "Sidekiq")
42
- dep.deprecate_methods(Sidekiq.singleton_class,
43
- default_worker_options: :default_job_options,
44
- "default_worker_options=": :default_job_options=)
46
+ initializer "sidekiq.backtrace_cleaner" do
47
+ Sidekiq.configure_server do |config|
48
+ config[:backtrace_cleaner] = ->(backtrace) { ::Rails.backtrace_cleaner.clean(backtrace) }
49
+ end
45
50
  end
46
51
 
47
52
  # This hook happens after all initializers are run, just before returning
@@ -55,10 +60,10 @@ module Sidekiq
55
60
  # This is the integration code necessary so that if a job uses `Rails.logger.info "Hello"`,
56
61
  # it will appear in the Sidekiq console with all of the job context.
57
62
  unless ::Rails.logger == config.logger || ::ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, $stdout)
58
- if ::Rails::VERSION::STRING < "7.1"
59
- ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
60
- else
63
+ if ::Rails.logger.respond_to?(:broadcast_to)
61
64
  ::Rails.logger.broadcast_to(config.logger)
65
+ else
66
+ ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
62
67
  end
63
68
  end
64
69
  end
@@ -1,15 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "connection_pool"
3
+ require "set"
4
4
  require "redis_client"
5
5
  require "redis_client/decorator"
6
- require "uri"
7
6
 
8
7
  module Sidekiq
9
8
  class RedisClientAdapter
10
9
  BaseError = RedisClient::Error
11
10
  CommandError = RedisClient::CommandError
12
11
 
12
+ # You can add/remove items or clear the whole thing if you don't want deprecation warnings.
13
+ DEPRECATED_COMMANDS = %i[rpoplpush zrangebyscore zrevrange zrevrangebyscore getset hmset setex setnx].to_set
14
+
13
15
  module CompatMethods
14
16
  def info
15
17
  @client.call("INFO") { |i| i.lines(chomp: true).map { |l| l.split(":", 2) }.select { |l| l.size == 2 }.to_h }
@@ -19,30 +21,28 @@ module Sidekiq
19
21
  @client.call("EVALSHA", sha, keys.size, *keys, *argv)
20
22
  end
21
23
 
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
24
+ # this is the set of Redis commands used by Sidekiq. Not guaranteed
25
+ # to be comprehensive, we use this as a performance enhancement to
26
+ # avoid calling method_missing on most commands
27
+ USED_COMMANDS = %w[bitfield bitfield_ro del exists expire flushdb
28
+ get hdel hget hgetall hincrby hlen hmget hset hsetnx incr incrby
29
+ lindex llen lmove lpop lpush lrange lrem mget mset ping pttl
30
+ publish rpop rpush sadd scard script set sismember smembers
31
+ srem ttl type unlink zadd zcard zincrby zrange zrem
32
+ zremrangebyrank zremrangebyscore]
29
33
 
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 }
34
+ USED_COMMANDS.each do |name|
35
+ define_method(name) do |*args, **kwargs|
36
+ @client.call(name, *args, **kwargs)
37
+ end
41
38
  end
42
39
 
43
40
  private
44
41
 
42
+ # this allows us to use methods like `conn.hmset(...)` instead of having to use
43
+ # redis-client's native `conn.call("hmset", ...)`
45
44
  def method_missing(*args, &block)
45
+ warn("[sidekiq#5788] Redis has deprecated the `#{args.first}`command, called at #{caller(1..1)}") if DEPRECATED_COMMANDS.include?(args.first)
46
46
  @client.call(*args, *block)
47
47
  end
48
48
  ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
@@ -55,47 +55,8 @@ module Sidekiq
55
55
  CompatClient = RedisClient::Decorator.create(CompatMethods)
56
56
 
57
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
58
+ def config
59
+ @client.config
99
60
  end
100
61
  end
101
62
 
@@ -118,9 +79,7 @@ module Sidekiq
118
79
  opts = options.dup
119
80
 
120
81
  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)
82
+ raise ArgumentError, "Your Redis configuration uses the namespace '#{opts[:namespace]}' but this feature is no longer supported in Sidekiq 7+. See https://github.com/sidekiq/sidekiq/blob/main/docs/7.0-Upgrade.md#redis-namespace."
124
83
  end
125
84
 
126
85
  opts.delete(:size)
@@ -150,5 +109,3 @@ module Sidekiq
150
109
  end
151
110
  end
152
111
  end
153
-
154
- Sidekiq::RedisConnection.adapter = Sidekiq::RedisClientAdapter