sidekiq 6.2.0 → 7.0.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.
- checksums.yaml +4 -4
- data/Changes.md +203 -5
- data/LICENSE.txt +9 -0
- data/README.md +20 -14
- data/bin/sidekiq +4 -9
- data/bin/sidekiqload +71 -76
- data/bin/sidekiqmon +1 -1
- data/lib/generators/sidekiq/job_generator.rb +57 -0
- data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
- data/lib/generators/sidekiq/templates/{worker_spec.rb.erb → job_spec.rb.erb} +1 -1
- data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
- data/lib/sidekiq/api.rb +334 -229
- data/lib/sidekiq/capsule.rb +110 -0
- data/lib/sidekiq/cli.rb +91 -79
- data/lib/sidekiq/client.rb +74 -85
- data/lib/sidekiq/{util.rb → component.rb} +13 -14
- data/lib/sidekiq/config.rb +271 -0
- data/lib/sidekiq/deploy.rb +62 -0
- data/lib/sidekiq/embedded.rb +61 -0
- data/lib/sidekiq/fetch.rb +26 -24
- data/lib/sidekiq/{worker.rb → job.rb} +162 -28
- data/lib/sidekiq/job_logger.rb +17 -29
- data/lib/sidekiq/job_retry.rb +79 -60
- data/lib/sidekiq/job_util.rb +71 -0
- data/lib/sidekiq/launcher.rb +96 -96
- data/lib/sidekiq/logger.rb +9 -44
- data/lib/sidekiq/manager.rb +40 -41
- data/lib/sidekiq/metrics/query.rb +153 -0
- data/lib/sidekiq/metrics/shared.rb +95 -0
- data/lib/sidekiq/metrics/tracking.rb +134 -0
- data/lib/sidekiq/middleware/chain.rb +89 -45
- data/lib/sidekiq/middleware/current_attributes.rb +58 -0
- data/lib/sidekiq/middleware/i18n.rb +6 -4
- data/lib/sidekiq/middleware/modules.rb +21 -0
- data/lib/sidekiq/monitor.rb +1 -1
- data/lib/sidekiq/paginator.rb +16 -8
- data/lib/sidekiq/processor.rb +56 -59
- data/lib/sidekiq/rails.rb +17 -5
- data/lib/sidekiq/redis_client_adapter.rb +118 -0
- data/lib/sidekiq/redis_connection.rb +17 -88
- data/lib/sidekiq/ring_buffer.rb +29 -0
- data/lib/sidekiq/scheduled.rb +102 -39
- data/lib/sidekiq/testing/inline.rb +4 -4
- data/lib/sidekiq/testing.rb +42 -71
- data/lib/sidekiq/transaction_aware_client.rb +44 -0
- data/lib/sidekiq/version.rb +2 -1
- data/lib/sidekiq/web/action.rb +3 -3
- data/lib/sidekiq/web/application.rb +33 -12
- data/lib/sidekiq/web/csrf_protection.rb +12 -9
- data/lib/sidekiq/web/helpers.rb +30 -40
- data/lib/sidekiq/web.rb +9 -19
- data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
- data/lib/sidekiq.rb +86 -201
- data/sidekiq.gemspec +30 -6
- data/web/assets/javascripts/application.js +113 -60
- data/web/assets/javascripts/base-charts.js +106 -0
- data/web/assets/javascripts/chart.min.js +13 -0
- data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
- data/web/assets/javascripts/dashboard-charts.js +166 -0
- data/web/assets/javascripts/dashboard.js +36 -273
- data/web/assets/javascripts/metrics.js +236 -0
- data/web/assets/stylesheets/application-dark.css +28 -45
- data/web/assets/stylesheets/application-rtl.css +2 -95
- data/web/assets/stylesheets/application.css +84 -529
- data/web/locales/ar.yml +71 -65
- data/web/locales/cs.yml +62 -62
- data/web/locales/da.yml +52 -52
- data/web/locales/de.yml +65 -65
- data/web/locales/el.yml +43 -24
- data/web/locales/en.yml +83 -67
- data/web/locales/es.yml +70 -54
- data/web/locales/fa.yml +65 -65
- data/web/locales/fr.yml +69 -62
- data/web/locales/he.yml +65 -64
- data/web/locales/hi.yml +59 -59
- data/web/locales/it.yml +53 -53
- data/web/locales/ja.yml +72 -66
- data/web/locales/ko.yml +52 -52
- data/web/locales/lt.yml +66 -66
- data/web/locales/nb.yml +61 -61
- data/web/locales/nl.yml +52 -52
- data/web/locales/pl.yml +45 -45
- data/web/locales/pt-br.yml +63 -55
- data/web/locales/pt.yml +51 -51
- data/web/locales/ru.yml +67 -66
- data/web/locales/sv.yml +53 -53
- data/web/locales/ta.yml +60 -60
- data/web/locales/uk.yml +62 -61
- data/web/locales/ur.yml +64 -64
- data/web/locales/vi.yml +67 -67
- data/web/locales/zh-cn.yml +37 -11
- data/web/locales/zh-tw.yml +42 -8
- data/web/views/_footer.erb +6 -3
- data/web/views/_job_info.erb +1 -1
- data/web/views/_nav.erb +1 -1
- data/web/views/_poll_link.erb +2 -5
- data/web/views/_summary.erb +7 -7
- data/web/views/busy.erb +17 -11
- data/web/views/dashboard.erb +58 -18
- data/web/views/dead.erb +1 -1
- data/web/views/layout.erb +1 -1
- data/web/views/metrics.erb +80 -0
- data/web/views/metrics_for_job.erb +69 -0
- data/web/views/morgue.erb +6 -6
- data/web/views/queue.erb +15 -11
- data/web/views/queues.erb +3 -3
- data/web/views/retries.erb +7 -7
- data/web/views/retry.erb +1 -1
- data/web/views/scheduled.erb +1 -1
- metadata +78 -28
- data/LICENSE +0 -9
- data/lib/generators/sidekiq/worker_generator.rb +0 -57
- data/lib/sidekiq/delay.rb +0 -41
- data/lib/sidekiq/exception_handler.rb +0 -27
- data/lib/sidekiq/extensions/action_mailer.rb +0 -48
- data/lib/sidekiq/extensions/active_record.rb +0 -43
- data/lib/sidekiq/extensions/class_methods.rb +0 -43
- data/lib/sidekiq/extensions/generic_proxy.rb +0 -31
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sidekiq
|
4
|
+
# Sidekiq::Job is a new alias for Sidekiq::Worker as of Sidekiq 6.3.0.
|
5
|
+
# Use `include Sidekiq::Job` rather than `include Sidekiq::Worker`.
|
6
|
+
#
|
7
|
+
# The term "worker" is too generic and overly confusing, used in several
|
8
|
+
# different contexts meaning different things. Many people call a Sidekiq
|
9
|
+
# process a "worker". Some people call the thread that executes jobs a
|
10
|
+
# "worker". This change brings Sidekiq closer to ActiveJob where your job
|
11
|
+
# classes extend ApplicationJob.
|
12
|
+
Worker = Job
|
13
|
+
end
|
data/lib/sidekiq.rb
CHANGED
@@ -1,13 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "sidekiq/version"
|
4
|
-
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.
|
4
|
+
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.7.0." if RUBY_PLATFORM != "java" && Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.7.0")
|
5
5
|
|
6
|
+
begin
|
7
|
+
require "sidekiq-ent/version"
|
8
|
+
fail <<~EOM if Gem::Version.new(Sidekiq::Enterprise::VERSION).segments[0] != Sidekiq::MAJOR
|
9
|
+
|
10
|
+
Sidekiq Enterprise #{Sidekiq::Enterprise::VERSION} does not work with Sidekiq #{Sidekiq::VERSION}.
|
11
|
+
Starting with Sidekiq 7, major versions are synchronized so Sidekiq Enterprise 7 works with Sidekiq 7.
|
12
|
+
Use `bundle up sidekiq-ent` to upgrade.
|
13
|
+
|
14
|
+
EOM
|
15
|
+
rescue LoadError
|
16
|
+
end
|
17
|
+
|
18
|
+
begin
|
19
|
+
require "sidekiq/pro/version"
|
20
|
+
fail <<~EOM if Gem::Version.new(Sidekiq::Pro::VERSION).segments[0] != Sidekiq::MAJOR
|
21
|
+
|
22
|
+
Sidekiq Pro #{Sidekiq::Pro::VERSION} does not work with Sidekiq #{Sidekiq::VERSION}.
|
23
|
+
Starting with Sidekiq 7, major versions are synchronized so Sidekiq Pro 7 works with Sidekiq 7.
|
24
|
+
Use `bundle up sidekiq-pro` to upgrade.
|
25
|
+
|
26
|
+
EOM
|
27
|
+
rescue LoadError
|
28
|
+
end
|
29
|
+
|
30
|
+
require "sidekiq/config"
|
6
31
|
require "sidekiq/logger"
|
7
32
|
require "sidekiq/client"
|
8
|
-
require "sidekiq/
|
9
|
-
require "sidekiq/
|
10
|
-
require "sidekiq/
|
33
|
+
require "sidekiq/transaction_aware_client"
|
34
|
+
require "sidekiq/job"
|
35
|
+
require "sidekiq/worker_compatibility_alias"
|
36
|
+
require "sidekiq/redis_client_adapter"
|
11
37
|
|
12
38
|
require "json"
|
13
39
|
|
@@ -15,247 +41,106 @@ module Sidekiq
|
|
15
41
|
NAME = "Sidekiq"
|
16
42
|
LICENSE = "See LICENSE and the LGPL-3.0 for licensing details."
|
17
43
|
|
18
|
-
DEFAULTS = {
|
19
|
-
queues: [],
|
20
|
-
labels: [],
|
21
|
-
concurrency: 10,
|
22
|
-
require: ".",
|
23
|
-
strict: true,
|
24
|
-
environment: nil,
|
25
|
-
timeout: 25,
|
26
|
-
poll_interval_average: nil,
|
27
|
-
average_scheduled_poll_interval: 5,
|
28
|
-
error_handlers: [],
|
29
|
-
death_handlers: [],
|
30
|
-
lifecycle_events: {
|
31
|
-
startup: [],
|
32
|
-
quiet: [],
|
33
|
-
shutdown: [],
|
34
|
-
heartbeat: []
|
35
|
-
},
|
36
|
-
dead_max_jobs: 10_000,
|
37
|
-
dead_timeout_in_seconds: 180 * 24 * 60 * 60, # 6 months
|
38
|
-
reloader: proc { |&block| block.call }
|
39
|
-
}
|
40
|
-
|
41
|
-
DEFAULT_WORKER_OPTIONS = {
|
42
|
-
"retry" => true,
|
43
|
-
"queue" => "default"
|
44
|
-
}
|
45
|
-
|
46
|
-
FAKE_INFO = {
|
47
|
-
"redis_version" => "9.9.9",
|
48
|
-
"uptime_in_days" => "9999",
|
49
|
-
"connected_clients" => "9999",
|
50
|
-
"used_memory_human" => "9P",
|
51
|
-
"used_memory_peak_human" => "9P"
|
52
|
-
}
|
53
|
-
|
54
44
|
def self.❨╯°□°❩╯︵┻━┻
|
55
|
-
puts "
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.options
|
59
|
-
@options ||= DEFAULTS.dup
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.options=(opts)
|
63
|
-
@options = opts
|
64
|
-
end
|
65
|
-
|
66
|
-
##
|
67
|
-
# Configuration for Sidekiq server, use like:
|
68
|
-
#
|
69
|
-
# Sidekiq.configure_server do |config|
|
70
|
-
# config.redis = { :namespace => 'myapp', :size => 25, :url => 'redis://myhost:8877/0' }
|
71
|
-
# config.server_middleware do |chain|
|
72
|
-
# chain.add MyServerHook
|
73
|
-
# end
|
74
|
-
# end
|
75
|
-
def self.configure_server
|
76
|
-
yield self if server?
|
77
|
-
end
|
78
|
-
|
79
|
-
##
|
80
|
-
# Configuration for Sidekiq client, use like:
|
81
|
-
#
|
82
|
-
# Sidekiq.configure_client do |config|
|
83
|
-
# config.redis = { :namespace => 'myapp', :size => 1, :url => 'redis://myhost:8877/0' }
|
84
|
-
# end
|
85
|
-
def self.configure_client
|
86
|
-
yield self unless server?
|
45
|
+
puts "Take a deep breath and count to ten..."
|
87
46
|
end
|
88
47
|
|
89
48
|
def self.server?
|
90
49
|
defined?(Sidekiq::CLI)
|
91
50
|
end
|
92
51
|
|
93
|
-
def self.
|
94
|
-
|
95
|
-
redis_pool.with do |conn|
|
96
|
-
retryable = true
|
97
|
-
begin
|
98
|
-
yield conn
|
99
|
-
rescue Redis::BaseError => ex
|
100
|
-
# 2550 Failover can cause the server to become a replica, need
|
101
|
-
# to disconnect and reopen the socket to get back to the primary.
|
102
|
-
# 4495 Use the same logic if we have a "Not enough replicas" error from the primary
|
103
|
-
if retryable && ex.message =~ /READONLY|NOREPLICAS/
|
104
|
-
conn.disconnect!
|
105
|
-
retryable = false
|
106
|
-
retry
|
107
|
-
end
|
108
|
-
raise
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
def self.redis_info
|
114
|
-
redis do |conn|
|
115
|
-
# admin commands can't go through redis-namespace starting
|
116
|
-
# in redis-namespace 2.0
|
117
|
-
if conn.respond_to?(:namespace)
|
118
|
-
conn.redis.info
|
119
|
-
else
|
120
|
-
conn.info
|
121
|
-
end
|
122
|
-
rescue Redis::CommandError => ex
|
123
|
-
# 2850 return fake version when INFO command has (probably) been renamed
|
124
|
-
raise unless /unknown command/.match?(ex.message)
|
125
|
-
FAKE_INFO
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def self.redis_pool
|
130
|
-
@redis ||= Sidekiq::RedisConnection.create
|
131
|
-
end
|
132
|
-
|
133
|
-
def self.redis=(hash)
|
134
|
-
@redis = if hash.is_a?(ConnectionPool)
|
135
|
-
hash
|
136
|
-
else
|
137
|
-
Sidekiq::RedisConnection.create(hash)
|
138
|
-
end
|
52
|
+
def self.load_json(string)
|
53
|
+
JSON.parse(string)
|
139
54
|
end
|
140
55
|
|
141
|
-
def self.
|
142
|
-
|
143
|
-
yield @client_chain if block_given?
|
144
|
-
@client_chain
|
56
|
+
def self.dump_json(object)
|
57
|
+
JSON.generate(object)
|
145
58
|
end
|
146
59
|
|
147
|
-
def self.
|
148
|
-
|
149
|
-
yield @server_chain if block_given?
|
150
|
-
@server_chain
|
60
|
+
def self.pro?
|
61
|
+
defined?(Sidekiq::Pro)
|
151
62
|
end
|
152
63
|
|
153
|
-
def self.
|
154
|
-
|
64
|
+
def self.ent?
|
65
|
+
defined?(Sidekiq::Enterprise)
|
155
66
|
end
|
156
67
|
|
157
|
-
def self.
|
158
|
-
|
159
|
-
@default_worker_options = default_worker_options.merge(hash.transform_keys(&:to_s))
|
68
|
+
def self.redis_pool
|
69
|
+
(Thread.current[:sidekiq_capsule] || default_configuration).redis_pool
|
160
70
|
end
|
161
71
|
|
162
|
-
def self.
|
163
|
-
|
72
|
+
def self.redis(&block)
|
73
|
+
(Thread.current[:sidekiq_capsule] || default_configuration).redis(&block)
|
164
74
|
end
|
165
75
|
|
166
|
-
|
167
|
-
|
168
|
-
# the job dies. It's the notification to your application
|
169
|
-
# that this job will not succeed without manual intervention.
|
170
|
-
#
|
171
|
-
# Sidekiq.configure_server do |config|
|
172
|
-
# config.death_handlers << ->(job, ex) do
|
173
|
-
# end
|
174
|
-
# end
|
175
|
-
def self.death_handlers
|
176
|
-
options[:death_handlers]
|
76
|
+
def self.strict_args!(mode = :raise)
|
77
|
+
Sidekiq::Config::DEFAULTS[:on_complex_arguments] = mode
|
177
78
|
end
|
178
79
|
|
179
|
-
def self.
|
180
|
-
|
80
|
+
def self.default_job_options=(hash)
|
81
|
+
@default_job_options = default_job_options.merge(hash.transform_keys(&:to_s))
|
181
82
|
end
|
182
83
|
|
183
|
-
def self.
|
184
|
-
|
84
|
+
def self.default_job_options
|
85
|
+
@default_job_options ||= {"retry" => true, "queue" => "default"}
|
185
86
|
end
|
186
87
|
|
187
|
-
def self.
|
188
|
-
@
|
189
|
-
Sidekiq::Logger::Formatters::WithoutTimestamp.new
|
190
|
-
else
|
191
|
-
Sidekiq::Logger::Formatters::Pretty.new
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def self.log_formatter=(log_formatter)
|
196
|
-
@log_formatter = log_formatter
|
197
|
-
logger.formatter = log_formatter
|
88
|
+
def self.default_configuration
|
89
|
+
@config ||= Sidekiq::Config.new
|
198
90
|
end
|
199
91
|
|
200
92
|
def self.logger
|
201
|
-
|
93
|
+
default_configuration.logger
|
202
94
|
end
|
203
95
|
|
204
|
-
def self.
|
205
|
-
|
206
|
-
|
207
|
-
return self.logger
|
208
|
-
end
|
209
|
-
|
210
|
-
logger.extend(Sidekiq::LoggingUtils)
|
211
|
-
|
212
|
-
@logger = logger
|
213
|
-
end
|
214
|
-
|
215
|
-
def self.pro?
|
216
|
-
defined?(Sidekiq::Pro)
|
96
|
+
def self.configure_server(&block)
|
97
|
+
(@config_blocks ||= []) << block
|
98
|
+
yield default_configuration if server?
|
217
99
|
end
|
218
100
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
#
|
223
|
-
# See sidekiq/scheduled.rb for an in-depth explanation of this value
|
224
|
-
def self.average_scheduled_poll_interval=(interval)
|
225
|
-
options[:average_scheduled_poll_interval] = interval
|
101
|
+
def self.freeze!
|
102
|
+
@frozen = true
|
103
|
+
@config_blocks = nil
|
226
104
|
end
|
227
105
|
|
228
|
-
#
|
106
|
+
# Creates a Sidekiq::Config instance that is more tuned for embedding
|
107
|
+
# within an arbitrary Ruby process. Notably it reduces concurrency by
|
108
|
+
# default so there is less contention for CPU time with other threads.
|
229
109
|
#
|
230
|
-
# Sidekiq.
|
231
|
-
# config.
|
110
|
+
# inst = Sidekiq.configure_embed do |config|
|
111
|
+
# config.queues = %w[critical default low]
|
232
112
|
# end
|
113
|
+
# inst.run
|
114
|
+
# sleep 10
|
115
|
+
# inst.terminate
|
116
|
+
#
|
117
|
+
# NB: it is really easy to overload a Ruby process with threads due to the GIL.
|
118
|
+
# I do not recommend setting concurrency higher than 2-3.
|
233
119
|
#
|
234
|
-
#
|
235
|
-
|
236
|
-
|
120
|
+
# NB: Sidekiq only supports one instance in memory. You will get undefined behavior
|
121
|
+
# if you try to embed Sidekiq twice in the same process.
|
122
|
+
def self.configure_embed(&block)
|
123
|
+
raise "Sidekiq global configuration is frozen, you must create all embedded instances BEFORE calling `run`" if @frozen
|
124
|
+
|
125
|
+
require "sidekiq/embedded"
|
126
|
+
cfg = default_configuration
|
127
|
+
cfg.concurrency = 2
|
128
|
+
@config_blocks&.each { |block| block.call(cfg) }
|
129
|
+
yield cfg
|
130
|
+
|
131
|
+
Sidekiq::Embedded.new(cfg)
|
237
132
|
end
|
238
133
|
|
239
|
-
|
240
|
-
|
241
|
-
#
|
242
|
-
# Sidekiq.configure_server do |config|
|
243
|
-
# config.on(:shutdown) do
|
244
|
-
# puts "Goodbye cruel world!"
|
245
|
-
# end
|
246
|
-
# end
|
247
|
-
def self.on(event, &block)
|
248
|
-
raise ArgumentError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
|
249
|
-
raise ArgumentError, "Invalid event name: #{event}" unless options[:lifecycle_events].key?(event)
|
250
|
-
options[:lifecycle_events][event] << block
|
134
|
+
def self.configure_client
|
135
|
+
yield default_configuration unless server?
|
251
136
|
end
|
252
137
|
|
253
|
-
# We are shutting down Sidekiq but what about
|
138
|
+
# We are shutting down Sidekiq but what about threads that
|
254
139
|
# are working on some long job? This error is
|
255
|
-
# raised in
|
140
|
+
# raised in jobs that have not finished within the hard
|
256
141
|
# timeout limit. This is needed to rollback db transactions,
|
257
142
|
# otherwise Ruby's Thread#kill will commit. See #377.
|
258
|
-
# DO NOT RESCUE THIS ERROR IN YOUR
|
143
|
+
# DO NOT RESCUE THIS ERROR IN YOUR JOBS
|
259
144
|
class Shutdown < Interrupt; end
|
260
145
|
end
|
261
146
|
|
data/sidekiq.gemspec
CHANGED
@@ -9,20 +9,44 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.license = "LGPL-3.0"
|
10
10
|
|
11
11
|
gem.executables = ["sidekiq", "sidekiqmon"]
|
12
|
-
gem.files = [
|
12
|
+
gem.files = %w[sidekiq.gemspec README.md Changes.md LICENSE.txt] + `git ls-files | grep -E '^(bin|lib|web)'`.split("\n")
|
13
13
|
gem.name = "sidekiq"
|
14
14
|
gem.version = Sidekiq::VERSION
|
15
|
-
gem.required_ruby_version = ">= 2.
|
15
|
+
gem.required_ruby_version = ">= 2.7.0"
|
16
16
|
|
17
17
|
gem.metadata = {
|
18
18
|
"homepage_uri" => "https://sidekiq.org",
|
19
19
|
"bug_tracker_uri" => "https://github.com/mperham/sidekiq/issues",
|
20
20
|
"documentation_uri" => "https://github.com/mperham/sidekiq/wiki",
|
21
|
-
"changelog_uri" => "https://github.com/mperham/sidekiq/blob/
|
21
|
+
"changelog_uri" => "https://github.com/mperham/sidekiq/blob/main/Changes.md",
|
22
22
|
"source_code_uri" => "https://github.com/mperham/sidekiq"
|
23
23
|
}
|
24
24
|
|
25
|
-
gem.add_dependency "redis", ">=
|
26
|
-
gem.add_dependency "connection_pool", ">= 2.
|
27
|
-
gem.add_dependency "rack", "
|
25
|
+
gem.add_dependency "redis-client", ">= 0.9.0"
|
26
|
+
gem.add_dependency "connection_pool", ">= 2.3.0"
|
27
|
+
gem.add_dependency "rack", ">= 2.2.4"
|
28
|
+
gem.add_dependency "concurrent-ruby", "< 2"
|
29
|
+
gem.post_install_message = <<~EOM
|
30
|
+
|
31
|
+
####################################################
|
32
|
+
|
33
|
+
|
34
|
+
█████████ █████ ██████████ ██████████ █████ ████ █████ ██████ ██████████ █████
|
35
|
+
███░░░░░███░░███ ░░███░░░░███ ░░███░░░░░█░░███ ███░ ░░███ ███░░░░███ ░███░░░░███ ███░░░███
|
36
|
+
░███ ░░░ ░███ ░███ ░░███ ░███ █ ░ ░███ ███ ░███ ███ ░░███ ░░░ ███ ███ ░░███
|
37
|
+
░░█████████ ░███ ░███ ░███ ░██████ ░███████ ░███ ░███ ░███ ███ ░███ ░███
|
38
|
+
░░░░░░░░███ ░███ ░███ ░███ ░███░░█ ░███░░███ ░███ ░███ ██░███ ███ ░███ ░███
|
39
|
+
███ ░███ ░███ ░███ ███ ░███ ░ █ ░███ ░░███ ░███ ░░███ ░░████ ███ ░░███ ███
|
40
|
+
░░█████████ █████ ██████████ ██████████ █████ ░░████ █████ ░░░██████░██ ███ ██ ░░░█████░
|
41
|
+
░░░░░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░ ░░░░░ ░░░░░░ ░░ ░░░ ░░ ░░░░░░
|
42
|
+
|
43
|
+
|
44
|
+
WARNING: This is a beta release, expect breakage!
|
45
|
+
|
46
|
+
1. Use `gem 'sidekiq', '<7'` in your Gemfile if you don't want to be a beta tester.
|
47
|
+
2. Read the release notes at https://github.com/mperham/sidekiq/blob/main/docs/7.0-Upgrade.md
|
48
|
+
3. Search for open/closed issues at https://github.com/mperham/sidekiq/issues/
|
49
|
+
|
50
|
+
####################################################
|
51
|
+
EOM
|
28
52
|
end
|