sidekiq 5.1.1 → 6.5.9

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 (126) hide show
  1. checksums.yaml +5 -5
  2. data/Changes.md +507 -1
  3. data/LICENSE +3 -3
  4. data/README.md +24 -35
  5. data/bin/sidekiq +27 -3
  6. data/bin/sidekiqload +80 -68
  7. data/bin/sidekiqmon +8 -0
  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 +537 -286
  13. data/lib/sidekiq/cli.rb +243 -240
  14. data/lib/sidekiq/client.rb +82 -85
  15. data/lib/sidekiq/component.rb +65 -0
  16. data/lib/sidekiq/delay.rb +9 -7
  17. data/lib/sidekiq/extensions/action_mailer.rb +13 -22
  18. data/lib/sidekiq/extensions/active_record.rb +13 -10
  19. data/lib/sidekiq/extensions/class_methods.rb +14 -11
  20. data/lib/sidekiq/extensions/generic_proxy.rb +7 -5
  21. data/lib/sidekiq/fetch.rb +50 -40
  22. data/lib/sidekiq/job.rb +13 -0
  23. data/lib/sidekiq/job_logger.rb +36 -9
  24. data/lib/sidekiq/job_retry.rb +143 -97
  25. data/lib/sidekiq/job_util.rb +71 -0
  26. data/lib/sidekiq/launcher.rb +185 -85
  27. data/lib/sidekiq/logger.rb +156 -0
  28. data/lib/sidekiq/manager.rb +41 -43
  29. data/lib/sidekiq/metrics/deploy.rb +47 -0
  30. data/lib/sidekiq/metrics/query.rb +153 -0
  31. data/lib/sidekiq/metrics/shared.rb +94 -0
  32. data/lib/sidekiq/metrics/tracking.rb +134 -0
  33. data/lib/sidekiq/middleware/chain.rb +102 -46
  34. data/lib/sidekiq/middleware/current_attributes.rb +63 -0
  35. data/lib/sidekiq/middleware/i18n.rb +7 -7
  36. data/lib/sidekiq/middleware/modules.rb +21 -0
  37. data/lib/sidekiq/monitor.rb +133 -0
  38. data/lib/sidekiq/paginator.rb +28 -16
  39. data/lib/sidekiq/processor.rb +156 -98
  40. data/lib/sidekiq/rails.rb +48 -42
  41. data/lib/sidekiq/redis_client_adapter.rb +154 -0
  42. data/lib/sidekiq/redis_connection.rb +109 -51
  43. data/lib/sidekiq/ring_buffer.rb +29 -0
  44. data/lib/sidekiq/scheduled.rb +133 -41
  45. data/lib/sidekiq/sd_notify.rb +149 -0
  46. data/lib/sidekiq/systemd.rb +24 -0
  47. data/lib/sidekiq/testing/inline.rb +6 -5
  48. data/lib/sidekiq/testing.rb +72 -62
  49. data/lib/sidekiq/transaction_aware_client.rb +45 -0
  50. data/lib/sidekiq/version.rb +2 -1
  51. data/lib/sidekiq/web/action.rb +15 -11
  52. data/lib/sidekiq/web/application.rb +127 -76
  53. data/lib/sidekiq/web/csrf_protection.rb +180 -0
  54. data/lib/sidekiq/web/helpers.rb +133 -96
  55. data/lib/sidekiq/web/router.rb +23 -19
  56. data/lib/sidekiq/web.rb +69 -109
  57. data/lib/sidekiq/worker.rb +268 -102
  58. data/lib/sidekiq.rb +175 -66
  59. data/sidekiq.gemspec +23 -23
  60. data/web/assets/images/apple-touch-icon.png +0 -0
  61. data/web/assets/javascripts/application.js +112 -61
  62. data/web/assets/javascripts/chart.min.js +13 -0
  63. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  64. data/web/assets/javascripts/dashboard.js +65 -91
  65. data/web/assets/javascripts/graph.js +16 -0
  66. data/web/assets/javascripts/metrics.js +262 -0
  67. data/web/assets/stylesheets/application-dark.css +143 -0
  68. data/web/assets/stylesheets/application-rtl.css +0 -4
  69. data/web/assets/stylesheets/application.css +120 -232
  70. data/web/assets/stylesheets/bootstrap.css +2 -2
  71. data/web/locales/ar.yml +9 -2
  72. data/web/locales/de.yml +14 -2
  73. data/web/locales/el.yml +43 -19
  74. data/web/locales/en.yml +14 -1
  75. data/web/locales/es.yml +21 -5
  76. data/web/locales/fr.yml +10 -3
  77. data/web/locales/ja.yml +14 -1
  78. data/web/locales/lt.yml +83 -0
  79. data/web/locales/pl.yml +4 -4
  80. data/web/locales/pt-br.yml +27 -9
  81. data/web/locales/ru.yml +4 -0
  82. data/web/locales/vi.yml +83 -0
  83. data/web/locales/zh-cn.yml +36 -11
  84. data/web/locales/zh-tw.yml +32 -7
  85. data/web/views/_footer.erb +4 -1
  86. data/web/views/_job_info.erb +3 -2
  87. data/web/views/_nav.erb +4 -18
  88. data/web/views/_poll_link.erb +2 -5
  89. data/web/views/_summary.erb +7 -7
  90. data/web/views/busy.erb +61 -22
  91. data/web/views/dashboard.erb +23 -14
  92. data/web/views/dead.erb +3 -3
  93. data/web/views/layout.erb +4 -2
  94. data/web/views/metrics.erb +69 -0
  95. data/web/views/metrics_for_job.erb +87 -0
  96. data/web/views/morgue.erb +9 -6
  97. data/web/views/queue.erb +24 -10
  98. data/web/views/queues.erb +11 -3
  99. data/web/views/retries.erb +14 -7
  100. data/web/views/retry.erb +3 -3
  101. data/web/views/scheduled.erb +5 -2
  102. metadata +62 -135
  103. data/.github/contributing.md +0 -32
  104. data/.github/issue_template.md +0 -11
  105. data/.gitignore +0 -13
  106. data/.travis.yml +0 -14
  107. data/3.0-Upgrade.md +0 -70
  108. data/4.0-Upgrade.md +0 -53
  109. data/5.0-Upgrade.md +0 -56
  110. data/COMM-LICENSE +0 -95
  111. data/Ent-Changes.md +0 -210
  112. data/Gemfile +0 -8
  113. data/Pro-2.0-Upgrade.md +0 -138
  114. data/Pro-3.0-Upgrade.md +0 -44
  115. data/Pro-4.0-Upgrade.md +0 -35
  116. data/Pro-Changes.md +0 -716
  117. data/Rakefile +0 -8
  118. data/bin/sidekiqctl +0 -99
  119. data/code_of_conduct.md +0 -50
  120. data/lib/generators/sidekiq/worker_generator.rb +0 -49
  121. data/lib/sidekiq/core_ext.rb +0 -1
  122. data/lib/sidekiq/exception_handler.rb +0 -29
  123. data/lib/sidekiq/logging.rb +0 -122
  124. data/lib/sidekiq/middleware/server/active_record.rb +0 -22
  125. data/lib/sidekiq/middleware/server/active_record_cache.rb +0 -11
  126. data/lib/sidekiq/util.rb +0 -66
data/lib/sidekiq.rb CHANGED
@@ -1,45 +1,47 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
- require 'sidekiq/version'
4
- fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.2.2." if RUBY_PLATFORM != 'java' && RUBY_VERSION < '2.2.2'
5
2
 
6
- require 'sidekiq/logging'
7
- require 'sidekiq/client'
8
- require 'sidekiq/worker'
9
- require 'sidekiq/redis_connection'
10
- require 'sidekiq/delay'
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")
11
5
 
12
- require 'json'
6
+ require "sidekiq/logger"
7
+ require "sidekiq/client"
8
+ require "sidekiq/transaction_aware_client"
9
+ require "sidekiq/worker"
10
+ require "sidekiq/job"
11
+ require "sidekiq/redis_connection"
12
+ require "sidekiq/delay"
13
+
14
+ require "json"
13
15
 
14
16
  module Sidekiq
15
- NAME = 'Sidekiq'.freeze
16
- LICENSE = 'See LICENSE and the LGPL-3.0 for licensing details.'
17
+ NAME = "Sidekiq"
18
+ LICENSE = "See LICENSE and the LGPL-3.0 for licensing details."
17
19
 
18
20
  DEFAULTS = {
19
21
  queues: [],
20
22
  labels: [],
21
- concurrency: 25,
22
- require: '.',
23
+ concurrency: 10,
24
+ require: ".",
25
+ strict: true,
23
26
  environment: nil,
24
- timeout: 8,
27
+ timeout: 25,
25
28
  poll_interval_average: nil,
26
29
  average_scheduled_poll_interval: 5,
30
+ on_complex_arguments: :warn,
27
31
  error_handlers: [],
28
32
  death_handlers: [],
29
33
  lifecycle_events: {
30
34
  startup: [],
31
35
  quiet: [],
32
36
  shutdown: [],
37
+ # triggers when we fire the first heartbeat on startup OR repairing a network partition
33
38
  heartbeat: [],
39
+ # triggers on EVERY heartbeat call, every 10 seconds
40
+ beat: []
34
41
  },
35
42
  dead_max_jobs: 10_000,
36
43
  dead_timeout_in_seconds: 180 * 24 * 60 * 60, # 6 months
37
- reloader: proc { |&block| block.call },
38
- }
39
-
40
- DEFAULT_WORKER_OPTIONS = {
41
- 'retry' => true,
42
- 'queue' => 'default'
44
+ reloader: proc { |&block| block.call }
43
45
  }
44
46
 
45
47
  FAKE_INFO = {
@@ -48,24 +50,90 @@ module Sidekiq
48
50
  "connected_clients" => "9999",
49
51
  "used_memory_human" => "9P",
50
52
  "used_memory_peak_human" => "9P"
51
- }.freeze
53
+ }
52
54
 
53
55
  def self.❨╯°□°❩╯︵┻━┻
54
56
  puts "Calm down, yo."
55
57
  end
56
58
 
59
+ # config.concurrency = 5
60
+ def self.concurrency=(val)
61
+ self[:concurrency] = Integer(val)
62
+ end
63
+
64
+ # config.queues = %w( high default low ) # strict
65
+ # config.queues = %w( high,3 default,2 low,1 ) # weighted
66
+ # config.queues = %w( feature1,1 feature2,1 feature3,1 ) # random
67
+ #
68
+ # With weighted priority, queue will be checked first (weight / total) of the time.
69
+ # high will be checked first (3/6) or 50% of the time.
70
+ # I'd recommend setting weights between 1-10. Weights in the hundreds or thousands
71
+ # are ridiculous and unnecessarily expensive. You can get random queue ordering
72
+ # by explicitly setting all weights to 1.
73
+ def self.queues=(val)
74
+ self[:queues] = Array(val).each_with_object([]) do |qstr, memo|
75
+ name, weight = qstr.split(",")
76
+ self[:strict] = false if weight.to_i > 0
77
+ [weight.to_i, 1].max.times do
78
+ memo << name
79
+ end
80
+ end
81
+ end
82
+
83
+ ### Private APIs
84
+ def self.default_error_handler(ex, ctx)
85
+ logger.warn(dump_json(ctx)) unless ctx.empty?
86
+ logger.warn("#{ex.class.name}: #{ex.message}")
87
+ logger.warn(ex.backtrace.join("\n")) unless ex.backtrace.nil?
88
+ end
89
+
90
+ # DEFAULT_ERROR_HANDLER is a constant that allows the default error handler to
91
+ # be referenced. It must be defined here, after the default_error_handler
92
+ # method is defined.
93
+ DEFAULT_ERROR_HANDLER = method(:default_error_handler)
94
+
95
+ @config = DEFAULTS.dup
57
96
  def self.options
58
- @options ||= DEFAULTS.dup
97
+ logger.warn "`config.options[:key] = value` is deprecated, use `config[:key] = value`: #{caller(1..2)}"
98
+ @config
59
99
  end
100
+
60
101
  def self.options=(opts)
61
- @options = opts
102
+ logger.warn "config.options = hash` is deprecated, use `config.merge!(hash)`: #{caller(1..2)}"
103
+ @config = opts
104
+ end
105
+
106
+ def self.[](key)
107
+ @config[key]
108
+ end
109
+
110
+ def self.[]=(key, val)
111
+ @config[key] = val
62
112
  end
63
113
 
114
+ def self.merge!(hash)
115
+ @config.merge!(hash)
116
+ end
117
+
118
+ def self.fetch(*args, &block)
119
+ @config.fetch(*args, &block)
120
+ end
121
+
122
+ def self.handle_exception(ex, ctx = {})
123
+ self[:error_handlers].each do |handler|
124
+ handler.call(ex, ctx)
125
+ rescue => ex
126
+ logger.error "!!! ERROR HANDLER THREW AN ERROR !!!"
127
+ logger.error ex
128
+ logger.error ex.backtrace.join("\n") unless ex.backtrace.nil?
129
+ end
130
+ end
131
+ ###
132
+
64
133
  ##
65
134
  # Configuration for Sidekiq server, use like:
66
135
  #
67
136
  # Sidekiq.configure_server do |config|
68
- # config.redis = { :namespace => 'myapp', :size => 25, :url => 'redis://myhost:8877/0' }
69
137
  # config.server_middleware do |chain|
70
138
  # chain.add MyServerHook
71
139
  # end
@@ -78,7 +146,7 @@ module Sidekiq
78
146
  # Configuration for Sidekiq client, use like:
79
147
  #
80
148
  # Sidekiq.configure_client do |config|
81
- # config.redis = { :namespace => 'myapp', :size => 1, :url => 'redis://myhost:8877/0' }
149
+ # config.redis = { size: 1, url: 'redis://myhost:8877/0' }
82
150
  # end
83
151
  def self.configure_client
84
152
  yield self unless server?
@@ -94,10 +162,17 @@ module Sidekiq
94
162
  retryable = true
95
163
  begin
96
164
  yield conn
97
- rescue Redis::CommandError => ex
98
- #2550 Failover can cause the server to become a slave, need
99
- # to disconnect and reopen the socket to get back to the master.
100
- (conn.disconnect!; retryable = false; retry) if retryable && ex.message =~ /READONLY/
165
+ rescue RedisConnection.adapter::BaseError => ex
166
+ # 2550 Failover can cause the server to become a replica, need
167
+ # to disconnect and reopen the socket to get back to the primary.
168
+ # 4495 Use the same logic if we have a "Not enough replicas" error from the primary
169
+ # 4985 Use the same logic when a blocking command is force-unblocked
170
+ # The same retry logic is also used in client.rb
171
+ if retryable && ex.message =~ /READONLY|NOREPLICAS|UNBLOCKED/
172
+ conn.disconnect!
173
+ retryable = false
174
+ retry
175
+ end
101
176
  raise
102
177
  end
103
178
  end
@@ -105,36 +180,34 @@ module Sidekiq
105
180
 
106
181
  def self.redis_info
107
182
  redis do |conn|
108
- begin
109
- # admin commands can't go through redis-namespace starting
110
- # in redis-namespace 2.0
111
- if conn.respond_to?(:namespace)
112
- conn.redis.info
113
- else
114
- conn.info
115
- end
116
- rescue Redis::CommandError => ex
117
- #2850 return fake version when INFO command has (probably) been renamed
118
- raise unless ex.message =~ /unknown command/
119
- FAKE_INFO
183
+ # admin commands can't go through redis-namespace starting
184
+ # in redis-namespace 2.0
185
+ if conn.respond_to?(:namespace)
186
+ conn.redis.info
187
+ else
188
+ conn.info
120
189
  end
190
+ rescue RedisConnection.adapter::CommandError => ex
191
+ # 2850 return fake version when INFO command has (probably) been renamed
192
+ raise unless /unknown command/.match?(ex.message)
193
+ FAKE_INFO
121
194
  end
122
195
  end
123
196
 
124
197
  def self.redis_pool
125
- @redis ||= Sidekiq::RedisConnection.create
198
+ @redis ||= RedisConnection.create
126
199
  end
127
200
 
128
201
  def self.redis=(hash)
129
202
  @redis = if hash.is_a?(ConnectionPool)
130
203
  hash
131
204
  else
132
- Sidekiq::RedisConnection.create(hash)
205
+ RedisConnection.create(hash)
133
206
  end
134
207
  end
135
208
 
136
209
  def self.client_middleware
137
- @client_chain ||= Middleware::Chain.new
210
+ @client_chain ||= Middleware::Chain.new(self)
138
211
  yield @client_chain if block_given?
139
212
  @client_chain
140
213
  end
@@ -146,21 +219,23 @@ module Sidekiq
146
219
  end
147
220
 
148
221
  def self.default_server_middleware
149
- Middleware::Chain.new
222
+ Middleware::Chain.new(self)
223
+ end
224
+
225
+ def self.default_worker_options=(hash) # deprecated
226
+ @default_job_options = default_job_options.merge(hash.transform_keys(&:to_s))
150
227
  end
151
228
 
152
- def self.default_worker_options=(hash)
153
- # stringify
154
- @default_worker_options = default_worker_options.merge(Hash[hash.map{|k, v| [k.to_s, v]}])
229
+ def self.default_job_options=(hash)
230
+ @default_job_options = default_job_options.merge(hash.transform_keys(&:to_s))
155
231
  end
156
- def self.default_worker_options
157
- defined?(@default_worker_options) ? @default_worker_options : DEFAULT_WORKER_OPTIONS
232
+
233
+ def self.default_worker_options # deprecated
234
+ @default_job_options ||= {"retry" => true, "queue" => "default"}
158
235
  end
159
236
 
160
- def self.default_retries_exhausted=(prok)
161
- logger.info { "default_retries_exhausted is deprecated, please use `config.death_handlers << -> {|job, ex| }`" }
162
- return nil unless prok
163
- death_handlers << prok
237
+ def self.default_job_options
238
+ @default_job_options ||= {"retry" => true, "queue" => "default"}
164
239
  end
165
240
 
166
241
  ##
@@ -173,21 +248,51 @@ module Sidekiq
173
248
  # end
174
249
  # end
175
250
  def self.death_handlers
176
- options[:death_handlers]
251
+ self[:death_handlers]
177
252
  end
178
253
 
179
254
  def self.load_json(string)
180
255
  JSON.parse(string)
181
256
  end
257
+
182
258
  def self.dump_json(object)
183
259
  JSON.generate(object)
184
260
  end
185
261
 
262
+ def self.log_formatter
263
+ @log_formatter ||= if ENV["DYNO"]
264
+ Sidekiq::Logger::Formatters::WithoutTimestamp.new
265
+ else
266
+ Sidekiq::Logger::Formatters::Pretty.new
267
+ end
268
+ end
269
+
270
+ def self.log_formatter=(log_formatter)
271
+ @log_formatter = log_formatter
272
+ logger.formatter = log_formatter
273
+ end
274
+
186
275
  def self.logger
187
- Sidekiq::Logging.logger
276
+ @logger ||= Sidekiq::Logger.new($stdout, level: :info)
277
+ end
278
+
279
+ def self.logger=(logger)
280
+ if logger.nil?
281
+ self.logger.level = Logger::FATAL
282
+ return self.logger
283
+ end
284
+
285
+ logger.extend(Sidekiq::LoggingUtils)
286
+
287
+ @logger = logger
288
+ end
289
+
290
+ def self.pro?
291
+ defined?(Sidekiq::Pro)
188
292
  end
189
- def self.logger=(log)
190
- Sidekiq::Logging.logger = log
293
+
294
+ def self.ent?
295
+ defined?(Sidekiq::Enterprise)
191
296
  end
192
297
 
193
298
  # How frequently Redis should be checked by a random Sidekiq process for
@@ -196,7 +301,7 @@ module Sidekiq
196
301
  #
197
302
  # See sidekiq/scheduled.rb for an in-depth explanation of this value
198
303
  def self.average_scheduled_poll_interval=(interval)
199
- self.options[:average_scheduled_poll_interval] = interval
304
+ self[:average_scheduled_poll_interval] = interval
200
305
  end
201
306
 
202
307
  # Register a proc to handle any error which occurs within the Sidekiq process.
@@ -207,7 +312,7 @@ module Sidekiq
207
312
  #
208
313
  # The default error handler logs errors to Sidekiq.logger.
209
314
  def self.error_handlers
210
- self.options[:error_handlers]
315
+ self[:error_handlers]
211
316
  end
212
317
 
213
318
  # Register a block to run at a point in the Sidekiq lifecycle.
@@ -220,17 +325,21 @@ module Sidekiq
220
325
  # end
221
326
  def self.on(event, &block)
222
327
  raise ArgumentError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
223
- raise ArgumentError, "Invalid event name: #{event}" unless options[:lifecycle_events].key?(event)
224
- options[:lifecycle_events][event] << block
328
+ raise ArgumentError, "Invalid event name: #{event}" unless self[:lifecycle_events].key?(event)
329
+ self[:lifecycle_events][event] << block
330
+ end
331
+
332
+ def self.strict_args!(mode = :raise)
333
+ self[:on_complex_arguments] = mode
225
334
  end
226
335
 
227
- # We are shutting down Sidekiq but what about workers that
336
+ # We are shutting down Sidekiq but what about threads that
228
337
  # are working on some long job? This error is
229
- # raised in workers that have not finished within the hard
338
+ # raised in jobs that have not finished within the hard
230
339
  # timeout limit. This is needed to rollback db transactions,
231
340
  # otherwise Ruby's Thread#kill will commit. See #377.
232
- # DO NOT RESCUE THIS ERROR IN YOUR WORKERS
341
+ # DO NOT RESCUE THIS ERROR IN YOUR JOBS
233
342
  class Shutdown < Interrupt; end
234
343
  end
235
344
 
236
- require 'sidekiq/rails' if defined?(::Rails::Engine)
345
+ require "sidekiq/rails" if defined?(::Rails::Engine)
data/sidekiq.gemspec CHANGED
@@ -1,28 +1,28 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/sidekiq/version', __FILE__)
1
+ require_relative "lib/sidekiq/version"
3
2
 
4
3
  Gem::Specification.new do |gem|
5
- gem.authors = ["Mike Perham"]
6
- gem.email = ["mperham@gmail.com"]
7
- gem.summary = "Simple, efficient background processing for Ruby"
8
- gem.description = "Simple, efficient background processing for Ruby."
9
- gem.homepage = "http://sidekiq.org"
10
- gem.license = "LGPL-3.0"
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 = "https://sidekiq.org"
9
+ gem.license = "LGPL-3.0"
11
10
 
12
- gem.executables = ['sidekiq', 'sidekiqctl']
13
- gem.files = `git ls-files | grep -Ev '^(test|myapp|examples)'`.split("\n")
14
- gem.test_files = []
15
- gem.name = "sidekiq"
16
- gem.require_paths = ["lib"]
17
- gem.version = Sidekiq::VERSION
18
- gem.required_ruby_version = ">= 2.2.2"
11
+ gem.executables = ["sidekiq", "sidekiqmon"]
12
+ gem.files = ["sidekiq.gemspec", "README.md", "Changes.md", "LICENSE"] + `git ls-files | grep -E '^(bin|lib|web)'`.split("\n")
13
+ gem.name = "sidekiq"
14
+ gem.version = Sidekiq::VERSION
15
+ gem.required_ruby_version = ">= 2.5.0"
19
16
 
20
- gem.add_dependency 'redis', '>= 3.3.5', '< 5'
21
- gem.add_dependency 'connection_pool', '~> 2.2', '>= 2.2.0'
22
- gem.add_dependency 'concurrent-ruby', '~> 1.0'
23
- gem.add_dependency 'rack-protection', '>= 1.5.0'
24
- gem.add_development_dependency 'redis-namespace', '~> 1.5', '>= 1.5.2'
25
- gem.add_development_dependency 'minitest', '~> 5.10', '>= 5.10.1'
26
- gem.add_development_dependency 'rake', '~> 10.0'
27
- gem.add_development_dependency 'rails', '>= 3.2.0'
17
+ gem.metadata = {
18
+ "homepage_uri" => "https://sidekiq.org",
19
+ "bug_tracker_uri" => "https://github.com/mperham/sidekiq/issues",
20
+ "documentation_uri" => "https://github.com/mperham/sidekiq/wiki",
21
+ "changelog_uri" => "https://github.com/mperham/sidekiq/blob/main/Changes.md",
22
+ "source_code_uri" => "https://github.com/mperham/sidekiq"
23
+ }
24
+
25
+ gem.add_dependency "redis", ["<5", ">= 4.5.0"]
26
+ gem.add_dependency "connection_pool", ["<3", ">= 2.2.5"]
27
+ gem.add_dependency "rack", "~> 2.0"
28
28
  end