sidekiq 7.0.1 → 7.0.3
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 +32 -0
- data/lib/sidekiq/api.rb +42 -3
- data/lib/sidekiq/capsule.rb +16 -0
- data/lib/sidekiq/cli.rb +2 -1
- data/lib/sidekiq/client.rb +1 -1
- data/lib/sidekiq/config.rb +2 -3
- data/lib/sidekiq/deploy.rb +3 -3
- data/lib/sidekiq/fetch.rb +2 -4
- data/lib/sidekiq/job.rb +2 -2
- data/lib/sidekiq/job_logger.rb +1 -1
- data/lib/sidekiq/job_retry.rb +1 -1
- data/lib/sidekiq/launcher.rb +11 -6
- data/lib/sidekiq/metrics/query.rb +1 -1
- data/lib/sidekiq/middleware/current_attributes.rb +5 -7
- data/lib/sidekiq/monitor.rb +17 -2
- data/lib/sidekiq/paginator.rb +2 -2
- data/lib/sidekiq/rails.rb +2 -1
- data/lib/sidekiq/redis_client_adapter.rb +3 -6
- data/lib/sidekiq/scheduled.rb +1 -1
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/application.rb +6 -3
- data/lib/sidekiq/web/helpers.rb +13 -5
- data/lib/sidekiq/web.rb +4 -0
- data/sidekiq.gemspec +4 -16
- data/web/assets/javascripts/application.js +18 -0
- data/web/assets/stylesheets/application-dark.css +4 -0
- data/web/assets/stylesheets/application.css +2 -2
- data/web/views/_job_info.erb +18 -2
- data/web/views/_paging.erb +2 -0
- data/web/views/busy.erb +36 -25
- data/web/views/metrics_for_job.erb +2 -2
- data/web/views/morgue.erb +5 -9
- data/web/views/queue.erb +10 -14
- data/web/views/queues.erb +3 -1
- data/web/views/retries.erb +5 -9
- data/web/views/scheduled.erb +12 -13
- metadata +8 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93289a9aed52b658b609cb6de99fefe182003d71bcc0102fa82fa33d53a70f5b
|
4
|
+
data.tar.gz: 1ca1b7ff222845a4a6f23ea00d77826c248a8e45db176eb9f2194afef70dface
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 680961f7df970445211487780291ecc1adb738fa834126428bbb814b0b7b03e912889c66020079f24aaf548a023c9621e601631d66dd6f7f467e9f8ac5085fee
|
7
|
+
data.tar.gz: cdd1e337afbba5aaea110227e8b91e1b965e05c6ff9a5b7f5202850e3725d4d6959137dd8f47075057230451e394dca3ca0cbe5c7d70ef33ac6284a21e7fbea4
|
data/Changes.md
CHANGED
@@ -2,6 +2,38 @@
|
|
2
2
|
|
3
3
|
[Sidekiq Changes](https://github.com/mperham/sidekiq/blob/main/Changes.md) | [Sidekiq Pro Changes](https://github.com/mperham/sidekiq/blob/main/Pro-Changes.md) | [Sidekiq Enterprise Changes](https://github.com/mperham/sidekiq/blob/main/Ent-Changes.md)
|
4
4
|
|
5
|
+
7.0.3
|
6
|
+
----------
|
7
|
+
|
8
|
+
- Don't warn about memory policy on Redis Enterprise [#5712]
|
9
|
+
- Don't allow Quiet/Stop on embedded Sidekiq instances [#5716]
|
10
|
+
- Fix `size: X` for configuring the default Redis pool size [#5702]
|
11
|
+
- Improve the display of queue weights on Busy page [#5642]
|
12
|
+
- Freeze CurrentAttributes on a job once initially set [#5692]
|
13
|
+
|
14
|
+
7.0.2
|
15
|
+
----------
|
16
|
+
|
17
|
+
- Improve compatibility with custom loggers [#5673]
|
18
|
+
- Add queue weights on Busy page [#5640]
|
19
|
+
- Add BID link on job_info page if job is part of a Batch [#5623]
|
20
|
+
- Allow custom extensions to add rows/links within Job detail pages [#5624]
|
21
|
+
```ruby
|
22
|
+
Sidekiq::Web.custom_job_info_rows << AddAccountLink.new
|
23
|
+
|
24
|
+
class AddAccountLink
|
25
|
+
include CGI::Util
|
26
|
+
def add_pair(job)
|
27
|
+
# yield a (name, value) pair
|
28
|
+
# You can include HTML tags and CSS, Sidekiq does not do any
|
29
|
+
# escaping so beware user data injection! Note how we use CGI's
|
30
|
+
# `h` escape helper.
|
31
|
+
aid = job["account_id"]
|
32
|
+
yield "Account", "<a href='/accounts/#{h aid}'>#{h aid}</a>" if aid
|
33
|
+
end
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
5
37
|
7.0.1
|
6
38
|
----------
|
7
39
|
|
data/lib/sidekiq/api.rb
CHANGED
@@ -418,6 +418,10 @@ module Sidekiq
|
|
418
418
|
self["jid"]
|
419
419
|
end
|
420
420
|
|
421
|
+
def bid
|
422
|
+
self["bid"]
|
423
|
+
end
|
424
|
+
|
421
425
|
def enqueued_at
|
422
426
|
self["enqueued_at"] ? Time.at(self["enqueued_at"]).utc : nil
|
423
427
|
end
|
@@ -824,6 +828,24 @@ module Sidekiq
|
|
824
828
|
class ProcessSet
|
825
829
|
include Enumerable
|
826
830
|
|
831
|
+
def self.[](identity)
|
832
|
+
exists, (info, busy, beat, quiet, rss, rtt_us) = Sidekiq.redis { |conn|
|
833
|
+
conn.multi { |transaction|
|
834
|
+
transaction.sismember("processes", identity)
|
835
|
+
transaction.hmget(identity, "info", "busy", "beat", "quiet", "rss", "rtt_us")
|
836
|
+
}
|
837
|
+
}
|
838
|
+
|
839
|
+
return nil if exists == 0 || info.nil?
|
840
|
+
|
841
|
+
hash = Sidekiq.load_json(info)
|
842
|
+
Process.new(hash.merge("busy" => busy.to_i,
|
843
|
+
"beat" => beat.to_f,
|
844
|
+
"quiet" => quiet,
|
845
|
+
"rss" => rss.to_i,
|
846
|
+
"rtt_us" => rtt_us.to_i))
|
847
|
+
end
|
848
|
+
|
827
849
|
# :nodoc:
|
828
850
|
# @api private
|
829
851
|
def initialize(clean_plz = true)
|
@@ -872,7 +894,7 @@ module Sidekiq
|
|
872
894
|
end
|
873
895
|
}
|
874
896
|
|
875
|
-
result.each do |info, busy,
|
897
|
+
result.each do |info, busy, beat, quiet, rss, rtt_us|
|
876
898
|
# If a process is stopped between when we query Redis for `procs` and
|
877
899
|
# when we query for `result`, we will have an item in `result` that is
|
878
900
|
# composed of `nil` values.
|
@@ -880,10 +902,10 @@ module Sidekiq
|
|
880
902
|
|
881
903
|
hash = Sidekiq.load_json(info)
|
882
904
|
yield Process.new(hash.merge("busy" => busy.to_i,
|
883
|
-
"beat" =>
|
905
|
+
"beat" => beat.to_f,
|
884
906
|
"quiet" => quiet,
|
885
907
|
"rss" => rss.to_i,
|
886
|
-
"rtt_us" =>
|
908
|
+
"rtt_us" => rtt_us.to_i))
|
887
909
|
end
|
888
910
|
end
|
889
911
|
|
@@ -939,6 +961,7 @@ module Sidekiq
|
|
939
961
|
# 'busy' => 10,
|
940
962
|
# 'beat' => <last heartbeat>,
|
941
963
|
# 'identity' => <unique string identifying the process>,
|
964
|
+
# 'embedded' => true,
|
942
965
|
# }
|
943
966
|
class Process
|
944
967
|
# :nodoc:
|
@@ -967,11 +990,25 @@ module Sidekiq
|
|
967
990
|
self["queues"]
|
968
991
|
end
|
969
992
|
|
993
|
+
def weights
|
994
|
+
self["weights"]
|
995
|
+
end
|
996
|
+
|
997
|
+
def version
|
998
|
+
self["version"]
|
999
|
+
end
|
1000
|
+
|
1001
|
+
def embedded?
|
1002
|
+
self["embedded"]
|
1003
|
+
end
|
1004
|
+
|
970
1005
|
# Signal this process to stop processing new jobs.
|
971
1006
|
# It will continue to execute jobs it has already fetched.
|
972
1007
|
# This method is *asynchronous* and it can take 5-10
|
973
1008
|
# seconds for the process to quiet.
|
974
1009
|
def quiet!
|
1010
|
+
raise "Can't quiet an embedded process" if embedded?
|
1011
|
+
|
975
1012
|
signal("TSTP")
|
976
1013
|
end
|
977
1014
|
|
@@ -980,6 +1017,8 @@ module Sidekiq
|
|
980
1017
|
# This method is *asynchronous* and it can take 5-10
|
981
1018
|
# seconds for the process to start shutting down.
|
982
1019
|
def stop!
|
1020
|
+
raise "Can't stop an embedded process" if embedded?
|
1021
|
+
|
983
1022
|
signal("TERM")
|
984
1023
|
end
|
985
1024
|
|
data/lib/sidekiq/capsule.rb
CHANGED
@@ -21,12 +21,15 @@ module Sidekiq
|
|
21
21
|
attr_reader :name
|
22
22
|
attr_reader :queues
|
23
23
|
attr_accessor :concurrency
|
24
|
+
attr_reader :mode
|
25
|
+
attr_reader :weights
|
24
26
|
|
25
27
|
def initialize(name, config)
|
26
28
|
@name = name
|
27
29
|
@config = config
|
28
30
|
@queues = ["default"]
|
29
31
|
@concurrency = config[:concurrency]
|
32
|
+
@mode = :strict
|
30
33
|
end
|
31
34
|
|
32
35
|
def fetcher
|
@@ -41,15 +44,28 @@ module Sidekiq
|
|
41
44
|
fetcher&.bulk_requeue([])
|
42
45
|
end
|
43
46
|
|
47
|
+
# Sidekiq checks queues in three modes:
|
48
|
+
# - :strict - all queues have 0 weight and are checked strictly in order
|
49
|
+
# - :weighted - queues have arbitrary weight between 1 and N
|
50
|
+
# - :random - all queues have weight of 1
|
44
51
|
def queues=(val)
|
52
|
+
@weights = {}
|
45
53
|
@queues = Array(val).each_with_object([]) do |qstr, memo|
|
46
54
|
arr = qstr
|
47
55
|
arr = qstr.split(",") if qstr.is_a?(String)
|
48
56
|
name, weight = arr
|
57
|
+
@weights[name] = weight.to_i
|
49
58
|
[weight.to_i, 1].max.times do
|
50
59
|
memo << name
|
51
60
|
end
|
52
61
|
end
|
62
|
+
@mode = if @weights.values.all?(&:zero?)
|
63
|
+
:strict
|
64
|
+
elsif @weights.values.all? { |x| x == 1 }
|
65
|
+
:random
|
66
|
+
else
|
67
|
+
:weighted
|
68
|
+
end
|
53
69
|
end
|
54
70
|
|
55
71
|
# Allow the middleware to be different per-capsule.
|
data/lib/sidekiq/cli.rb
CHANGED
@@ -77,7 +77,8 @@ module Sidekiq # :nodoc:
|
|
77
77
|
raise "You are connecting to Redis #{ver}, Sidekiq requires Redis 6.2.0 or greater" if ver < Gem::Version.new("6.2.0")
|
78
78
|
|
79
79
|
maxmemory_policy = info["maxmemory_policy"]
|
80
|
-
if maxmemory_policy != "noeviction"
|
80
|
+
if maxmemory_policy != "noeviction" && maxmemory_policy != ""
|
81
|
+
# Redis Enterprise Cloud returns "" for their policy 😳
|
81
82
|
logger.warn <<~EOM
|
82
83
|
|
83
84
|
|
data/lib/sidekiq/client.rb
CHANGED
@@ -189,7 +189,7 @@ module Sidekiq
|
|
189
189
|
def enqueue_to_in(queue, interval, klass, *args)
|
190
190
|
int = interval.to_f
|
191
191
|
now = Time.now.to_f
|
192
|
-
ts = (int < 1_000_000_000 ? now + int : int)
|
192
|
+
ts = ((int < 1_000_000_000) ? now + int : int)
|
193
193
|
|
194
194
|
item = {"class" => klass, "args" => args, "at" => ts, "queue" => queue}
|
195
195
|
item.delete("at") if ts <= now
|
data/lib/sidekiq/config.rb
CHANGED
@@ -129,12 +129,12 @@ module Sidekiq
|
|
129
129
|
def new_redis_pool(size, name = "unset")
|
130
130
|
# connection pool is lazy, it will not create connections unless you actually need them
|
131
131
|
# so don't be skimpy!
|
132
|
-
RedisConnection.create(
|
132
|
+
RedisConnection.create({size: size, logger: logger, pool_name: name}.merge(@redis_config))
|
133
133
|
end
|
134
134
|
|
135
135
|
def redis_info
|
136
136
|
redis do |conn|
|
137
|
-
conn.
|
137
|
+
conn.call("INFO") { |i| i.lines(chomp: true).map { |l| l.split(":", 2) }.select { |l| l.size == 2 }.to_h }
|
138
138
|
rescue RedisClientAdapter::CommandError => ex
|
139
139
|
# 2850 return fake version when INFO command has (probably) been renamed
|
140
140
|
raise unless /unknown command/.match?(ex.message)
|
@@ -248,7 +248,6 @@ module Sidekiq
|
|
248
248
|
return
|
249
249
|
end
|
250
250
|
|
251
|
-
logger.extend(Sidekiq::LoggingUtils)
|
252
251
|
@logger = logger
|
253
252
|
end
|
254
253
|
|
data/lib/sidekiq/deploy.rb
CHANGED
@@ -21,15 +21,15 @@ module Sidekiq
|
|
21
21
|
}
|
22
22
|
|
23
23
|
def self.mark!(label = nil)
|
24
|
-
label
|
25
|
-
Sidekiq::Deploy.new.mark(label: label)
|
24
|
+
Sidekiq::Deploy.new.mark!(label: label)
|
26
25
|
end
|
27
26
|
|
28
27
|
def initialize(pool = Sidekiq::RedisConnection.create)
|
29
28
|
@pool = pool
|
30
29
|
end
|
31
30
|
|
32
|
-
def mark(at: Time.now, label:
|
31
|
+
def mark!(at: Time.now, label: nil)
|
32
|
+
label ||= LABEL_MAKER.call
|
33
33
|
# we need to round the timestamp so that we gracefully
|
34
34
|
# handle an very common error in marking deploys:
|
35
35
|
# having every process mark its deploy, leading
|
data/lib/sidekiq/fetch.rb
CHANGED
@@ -30,11 +30,9 @@ module Sidekiq # :nodoc:
|
|
30
30
|
def initialize(cap)
|
31
31
|
raise ArgumentError, "missing queue list" unless cap.queues
|
32
32
|
@config = cap
|
33
|
-
@strictly_ordered_queues =
|
33
|
+
@strictly_ordered_queues = cap.mode == :strict
|
34
34
|
@queues = config.queues.map { |q| "queue:#{q}" }
|
35
|
-
if @strictly_ordered_queues
|
36
|
-
@queues.uniq!
|
37
|
-
end
|
35
|
+
@queues.uniq! if @strictly_ordered_queues
|
38
36
|
end
|
39
37
|
|
40
38
|
def retrieve_work
|
data/lib/sidekiq/job.rb
CHANGED
@@ -258,7 +258,7 @@ module Sidekiq
|
|
258
258
|
def at(interval)
|
259
259
|
int = interval.to_f
|
260
260
|
now = Time.now.to_f
|
261
|
-
ts = (int < 1_000_000_000 ? now + int : int)
|
261
|
+
ts = ((int < 1_000_000_000) ? now + int : int)
|
262
262
|
# Optimization to enqueue something now that is scheduled to go out now or in the past
|
263
263
|
@opts["at"] = ts if ts > now
|
264
264
|
self
|
@@ -325,7 +325,7 @@ module Sidekiq
|
|
325
325
|
def perform_in(interval, *args)
|
326
326
|
int = interval.to_f
|
327
327
|
now = Time.now.to_f
|
328
|
-
ts = (int < 1_000_000_000 ? now + int : int)
|
328
|
+
ts = ((int < 1_000_000_000) ? now + int : int)
|
329
329
|
|
330
330
|
item = {"class" => self, "args" => args}
|
331
331
|
|
data/lib/sidekiq/job_logger.rb
CHANGED
data/lib/sidekiq/job_retry.rb
CHANGED
@@ -49,7 +49,7 @@ module Sidekiq
|
|
49
49
|
# The default number of retries is 25 which works out to about 3 weeks
|
50
50
|
# You can change the default maximum number of retries in your initializer:
|
51
51
|
#
|
52
|
-
# Sidekiq.
|
52
|
+
# Sidekiq.default_configuration[:max_retries] = 7
|
53
53
|
#
|
54
54
|
# or limit the number of retries for a particular job and send retries to
|
55
55
|
# a low priority queue with:
|
data/lib/sidekiq/launcher.rb
CHANGED
@@ -161,7 +161,7 @@ module Sidekiq
|
|
161
161
|
fails = procd = 0
|
162
162
|
kb = memory_usage(::Process.pid)
|
163
163
|
|
164
|
-
_, exists, _, _,
|
164
|
+
_, exists, _, _, signal = redis { |conn|
|
165
165
|
conn.multi { |transaction|
|
166
166
|
transaction.sadd("processes", [key])
|
167
167
|
transaction.exists(key)
|
@@ -180,9 +180,7 @@ module Sidekiq
|
|
180
180
|
fire_event(:heartbeat) unless exists > 0
|
181
181
|
fire_event(:beat, oneshot: false)
|
182
182
|
|
183
|
-
|
184
|
-
|
185
|
-
::Process.kill(msg, ::Process.pid)
|
183
|
+
::Process.kill(signal, ::Process.pid) if signal && !@embedded
|
186
184
|
rescue => e
|
187
185
|
# ignore all redis/network issues
|
188
186
|
logger.error("heartbeat: #{e}")
|
@@ -250,12 +248,19 @@ module Sidekiq
|
|
250
248
|
"pid" => ::Process.pid,
|
251
249
|
"tag" => @config[:tag] || "",
|
252
250
|
"concurrency" => @config.total_concurrency,
|
253
|
-
"queues" => @config.capsules.values.
|
251
|
+
"queues" => @config.capsules.values.flat_map { |cap| cap.queues }.uniq,
|
252
|
+
"weights" => to_weights,
|
254
253
|
"labels" => @config[:labels].to_a,
|
255
|
-
"identity" => identity
|
254
|
+
"identity" => identity,
|
255
|
+
"version" => Sidekiq::VERSION,
|
256
|
+
"embedded" => @embedded
|
256
257
|
}
|
257
258
|
end
|
258
259
|
|
260
|
+
def to_weights
|
261
|
+
@config.capsules.values.map(&:weights)
|
262
|
+
end
|
263
|
+
|
259
264
|
def to_json
|
260
265
|
# this data changes infrequently so dump it to a string
|
261
266
|
# now so we don't need to dump it every heartbeat.
|
@@ -123,7 +123,7 @@ module Sidekiq
|
|
123
123
|
def series_avg(metric = "ms")
|
124
124
|
series[metric].each_with_object(Hash.new(0)) do |(bucket, value), result|
|
125
125
|
completed = series.dig("p", bucket) - series.dig("f", bucket)
|
126
|
-
result[bucket] = completed == 0 ? 0 : value.to_f / completed
|
126
|
+
result[bucket] = (completed == 0) ? 0 : value.to_f / completed
|
127
127
|
end
|
128
128
|
end
|
129
129
|
end
|
@@ -22,13 +22,11 @@ module Sidekiq
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def call(_, job, _, _)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
job["cattr"] = attrs
|
31
|
-
end
|
25
|
+
if !job.has_key?("cattr")
|
26
|
+
attrs = @strklass.constantize.attributes
|
27
|
+
# Retries can push the job N times, we don't
|
28
|
+
# want retries to reset cattr. #5692, #5090
|
29
|
+
job["cattr"] = attrs if attrs.any?
|
32
30
|
end
|
33
31
|
yield
|
34
32
|
end
|
data/lib/sidekiq/monitor.rb
CHANGED
@@ -49,10 +49,25 @@ class Sidekiq::Monitor
|
|
49
49
|
def processes
|
50
50
|
puts "---- Processes (#{process_set.size}) ----"
|
51
51
|
process_set.each_with_index do |process, index|
|
52
|
+
# Keep compatibility with legacy versions since we don't want to break sidekiqmon during rolling upgrades or downgrades.
|
53
|
+
#
|
54
|
+
# Before:
|
55
|
+
# ["default", "critical"]
|
56
|
+
#
|
57
|
+
# After:
|
58
|
+
# {"default" => 1, "critical" => 10}
|
59
|
+
queues =
|
60
|
+
if process["weights"]
|
61
|
+
process["weights"].sort_by { |queue| queue[0] }.map { |queue| queue.join(": ") }
|
62
|
+
else
|
63
|
+
process["queues"].sort
|
64
|
+
end
|
65
|
+
|
52
66
|
puts "#{process["identity"]} #{tags_for(process)}"
|
53
67
|
puts " Started: #{Time.at(process["started_at"])} (#{time_ago(process["started_at"])})"
|
54
68
|
puts " Threads: #{process["concurrency"]} (#{process["busy"]} busy)"
|
55
|
-
puts " Queues: #{split_multiline(
|
69
|
+
puts " Queues: #{split_multiline(queues, pad: 11)}"
|
70
|
+
puts " Version: #{process["version"] || "Unknown"}" if process["version"] != Sidekiq::VERSION
|
56
71
|
puts "" unless (index + 1) == process_set.size
|
57
72
|
end
|
58
73
|
end
|
@@ -101,7 +116,7 @@ class Sidekiq::Monitor
|
|
101
116
|
tags = [
|
102
117
|
process["tag"],
|
103
118
|
process["labels"],
|
104
|
-
(process["quiet"] == "true" ? "quiet" : nil)
|
119
|
+
((process["quiet"] == "true") ? "quiet" : nil)
|
105
120
|
].flatten.compact
|
106
121
|
tags.any? ? "[#{tags.join("] [")}]" : nil
|
107
122
|
end
|
data/lib/sidekiq/paginator.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Sidekiq
|
4
4
|
module Paginator
|
5
5
|
def page(key, pageidx = 1, page_size = 25, opts = nil)
|
6
|
-
current_page = pageidx.to_i < 1 ? 1 : pageidx.to_i
|
6
|
+
current_page = (pageidx.to_i < 1) ? 1 : pageidx.to_i
|
7
7
|
pageidx = current_page - 1
|
8
8
|
total_size = 0
|
9
9
|
items = []
|
@@ -45,7 +45,7 @@ module Sidekiq
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def page_items(items, pageidx = 1, page_size = 25)
|
48
|
-
current_page = pageidx.to_i < 1 ? 1 : pageidx.to_i
|
48
|
+
current_page = (pageidx.to_i < 1) ? 1 : pageidx.to_i
|
49
49
|
pageidx = current_page - 1
|
50
50
|
starting = pageidx * page_size
|
51
51
|
items = items.to_a
|
data/lib/sidekiq/rails.rb
CHANGED
@@ -9,10 +9,12 @@ module Sidekiq
|
|
9
9
|
CommandError = RedisClient::CommandError
|
10
10
|
|
11
11
|
module CompatMethods
|
12
|
+
# TODO Deprecate and remove this
|
12
13
|
def info
|
13
14
|
@client.call("INFO") { |i| i.lines(chomp: true).map { |l| l.split(":", 2) }.select { |l| l.size == 2 }.to_h }
|
14
15
|
end
|
15
16
|
|
17
|
+
# TODO Deprecate and remove this
|
16
18
|
def evalsha(sha, keys, argv)
|
17
19
|
@client.call("EVALSHA", sha, keys.size, *keys, *argv)
|
18
20
|
end
|
@@ -34,12 +36,7 @@ module Sidekiq
|
|
34
36
|
CompatClient = RedisClient::Decorator.create(CompatMethods)
|
35
37
|
|
36
38
|
class CompatClient
|
37
|
-
|
38
|
-
def _client
|
39
|
-
@client
|
40
|
-
end
|
41
|
-
|
42
|
-
def _config
|
39
|
+
def config
|
43
40
|
@client.config
|
44
41
|
end
|
45
42
|
|
data/lib/sidekiq/scheduled.rb
CHANGED
@@ -54,7 +54,7 @@ module Sidekiq
|
|
54
54
|
@lua_zpopbyscore_sha = conn.script(:load, LUA_ZPOPBYSCORE)
|
55
55
|
end
|
56
56
|
|
57
|
-
conn.
|
57
|
+
conn.call("EVALSHA", @lua_zpopbyscore_sha, keys.size, *keys, *argv)
|
58
58
|
rescue RedisClient::CommandError => e
|
59
59
|
raise unless e.message.start_with?("NOSCRIPT")
|
60
60
|
|
data/lib/sidekiq/version.rb
CHANGED
@@ -82,11 +82,14 @@ module Sidekiq
|
|
82
82
|
|
83
83
|
post "/busy" do
|
84
84
|
if params["identity"]
|
85
|
-
|
86
|
-
|
87
|
-
|
85
|
+
pro = Sidekiq::ProcessSet[params["identity"]]
|
86
|
+
|
87
|
+
pro.quiet! if params["quiet"]
|
88
|
+
pro.stop! if params["stop"]
|
88
89
|
else
|
89
90
|
processes.each do |pro|
|
91
|
+
next if pro.embedded?
|
92
|
+
|
90
93
|
pro.quiet! if params["quiet"]
|
91
94
|
pro.stop! if params["stop"]
|
92
95
|
end
|
data/lib/sidekiq/web/helpers.rb
CHANGED
@@ -137,7 +137,7 @@ module Sidekiq
|
|
137
137
|
end
|
138
138
|
|
139
139
|
def sort_direction_label
|
140
|
-
params[:direction] == "asc" ? "↑" : "↓"
|
140
|
+
(params[:direction] == "asc") ? "↑" : "↓"
|
141
141
|
end
|
142
142
|
|
143
143
|
def workset
|
@@ -161,13 +161,21 @@ module Sidekiq
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
164
|
+
def busy_weights(capsule_weights)
|
165
|
+
# backwards compat with 7.0.0, remove in 7.1
|
166
|
+
cw = [capsule_weights].flatten
|
167
|
+
cw.map { |hash|
|
168
|
+
hash.map { |name, weight| (weight > 0) ? +name << ": " << weight.to_s : name }.join(", ")
|
169
|
+
}.join("; ")
|
170
|
+
end
|
171
|
+
|
164
172
|
def stats
|
165
173
|
@stats ||= Sidekiq::Stats.new
|
166
174
|
end
|
167
175
|
|
168
176
|
def redis_url
|
169
177
|
Sidekiq.redis do |conn|
|
170
|
-
conn.
|
178
|
+
conn.config.server_url
|
171
179
|
end
|
172
180
|
end
|
173
181
|
|
@@ -184,7 +192,7 @@ module Sidekiq
|
|
184
192
|
end
|
185
193
|
|
186
194
|
def current_status
|
187
|
-
workset.size == 0 ? "idle" : "active"
|
195
|
+
(workset.size == 0) ? "idle" : "active"
|
188
196
|
end
|
189
197
|
|
190
198
|
def relative_time(time)
|
@@ -217,7 +225,7 @@ module Sidekiq
|
|
217
225
|
end
|
218
226
|
|
219
227
|
def truncate(text, truncate_after_chars = 2000)
|
220
|
-
truncate_after_chars && text.size > truncate_after_chars ? "#{text[0..truncate_after_chars]}..." : text
|
228
|
+
(truncate_after_chars && text.size > truncate_after_chars) ? "#{text[0..truncate_after_chars]}..." : text
|
221
229
|
end
|
222
230
|
|
223
231
|
def display_args(args, truncate_after_chars = 2000)
|
@@ -324,7 +332,7 @@ module Sidekiq
|
|
324
332
|
end
|
325
333
|
|
326
334
|
def pollable?
|
327
|
-
!(current_path == "" || current_path.
|
335
|
+
!(current_path == "" || current_path.start_with?("metrics"))
|
328
336
|
end
|
329
337
|
|
330
338
|
def retry_or_delete_or_kill(job, params)
|
data/lib/sidekiq/web.rb
CHANGED
data/sidekiq.gemspec
CHANGED
@@ -22,29 +22,17 @@ Gem::Specification.new do |gem|
|
|
22
22
|
"source_code_uri" => "https://github.com/mperham/sidekiq"
|
23
23
|
}
|
24
24
|
|
25
|
-
gem.add_dependency "redis-client", ">= 0.
|
25
|
+
gem.add_dependency "redis-client", ">= 0.11.0"
|
26
26
|
gem.add_dependency "connection_pool", ">= 2.3.0"
|
27
27
|
gem.add_dependency "rack", ">= 2.2.4"
|
28
28
|
gem.add_dependency "concurrent-ruby", "< 2"
|
29
29
|
gem.post_install_message = <<~EOM
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
█████████ █████ ██████████ ██████████ █████ ████ █████ ██████ ██████████ █████
|
35
|
-
███░░░░░███░░███ ░░███░░░░███ ░░███░░░░░█░░███ ███░ ░░███ ███░░░░███ ░███░░░░███ ███░░░███
|
36
|
-
░███ ░░░ ░███ ░███ ░░███ ░███ █ ░ ░███ ███ ░███ ███ ░░███ ░░░ ███ ███ ░░███
|
37
|
-
░░█████████ ░███ ░███ ░███ ░██████ ░███████ ░███ ░███ ░███ ███ ░███ ░███
|
38
|
-
░░░░░░░░███ ░███ ░███ ░███ ░███░░█ ░███░░███ ░███ ░███ ██░███ ███ ░███ ░███
|
39
|
-
███ ░███ ░███ ░███ ███ ░███ ░ █ ░███ ░░███ ░███ ░░███ ░░████ ███ ░░███ ███
|
40
|
-
░░█████████ █████ ██████████ ██████████ █████ ░░████ █████ ░░░██████░██ ███ ██ ░░░█████░
|
41
|
-
░░░░░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░ ░░░░░ ░░░░░░ ░░ ░░░ ░░ ░░░░░░
|
42
|
-
|
31
|
+
Welcome to Sidekiq 7.0!
|
43
32
|
|
44
33
|
1. Use `gem 'sidekiq', '<7'` in your Gemfile if you don't want this new version.
|
45
34
|
2. Read the release notes at https://github.com/mperham/sidekiq/blob/main/docs/7.0-Upgrade.md
|
46
|
-
3.
|
47
|
-
|
48
|
-
####################################################
|
35
|
+
3. If you have problems, search for open/closed issues at https://github.com/mperham/sidekiq/issues/
|
36
|
+
|
49
37
|
EOM
|
50
38
|
end
|
@@ -31,6 +31,7 @@ function addListeners() {
|
|
31
31
|
node.addEventListener("click", addDataToggleListeners)
|
32
32
|
})
|
33
33
|
|
34
|
+
addShiftClickListeners()
|
34
35
|
updateFuzzyTimes();
|
35
36
|
setLivePollFromUrl();
|
36
37
|
|
@@ -71,6 +72,23 @@ function addDataToggleListeners(event) {
|
|
71
72
|
}
|
72
73
|
}
|
73
74
|
|
75
|
+
function addShiftClickListeners() {
|
76
|
+
let checkboxes = Array.from(document.querySelectorAll(".shift_clickable"));
|
77
|
+
let lastChecked = null;
|
78
|
+
checkboxes.forEach(checkbox => {
|
79
|
+
checkbox.addEventListener("click", (e) => {
|
80
|
+
if (e.shiftKey && lastChecked) {
|
81
|
+
let myIndex = checkboxes.indexOf(checkbox);
|
82
|
+
let lastIndex = checkboxes.indexOf(lastChecked);
|
83
|
+
let [min, max] = [myIndex, lastIndex].sort();
|
84
|
+
let newState = checkbox.checked;
|
85
|
+
checkboxes.slice(min, max).forEach(c => c.checked = newState);
|
86
|
+
}
|
87
|
+
lastChecked = checkbox;
|
88
|
+
});
|
89
|
+
});
|
90
|
+
}
|
91
|
+
|
74
92
|
function updateFuzzyTimes() {
|
75
93
|
var locale = document.body.getAttribute("data-locale");
|
76
94
|
var parts = locale.split('-');
|
data/web/views/_job_info.erb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
<header>
|
1
|
+
<div class="header-container">
|
2
2
|
<h3><%= t('Job') %></h3>
|
3
|
-
</
|
3
|
+
</div>
|
4
4
|
|
5
5
|
<div class="table_container">
|
6
6
|
<table class="table table-bordered table-striped table-hover">
|
@@ -33,6 +33,14 @@
|
|
33
33
|
<code><%= job.jid %></code>
|
34
34
|
</td>
|
35
35
|
</tr>
|
36
|
+
<% if job.bid %>
|
37
|
+
<tr>
|
38
|
+
<th>BID</th>
|
39
|
+
<td>
|
40
|
+
<a href="<%= root_path %>batches/<%= job.bid %>"><%= job.bid %>
|
41
|
+
</td>
|
42
|
+
</tr>
|
43
|
+
<% end %>
|
36
44
|
<tr>
|
37
45
|
<th><%= t('CreatedAt') %></th>
|
38
46
|
<td><%= relative_time(job.created_at) %></td>
|
@@ -84,6 +92,14 @@
|
|
84
92
|
<td><%= relative_time(job.at) if job['retry_count'] %></td>
|
85
93
|
</tr>
|
86
94
|
<% end %>
|
95
|
+
<% Sidekiq::Web.custom_job_info_rows.each do |helper| %>
|
96
|
+
<% helper.add_pair(job) do |name, value| %>
|
97
|
+
<tr>
|
98
|
+
<th><%= name %></th>
|
99
|
+
<td><%= value %></td>
|
100
|
+
</tr>
|
101
|
+
<% end %>
|
102
|
+
<% end %>
|
87
103
|
</tbody>
|
88
104
|
</table>
|
89
105
|
</div>
|
data/web/views/_paging.erb
CHANGED
data/web/views/busy.erb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
<div class="
|
2
|
-
<
|
3
|
-
<h3><%= t('Status') %></h3>
|
4
|
-
</div>
|
1
|
+
<div class="header-container">
|
2
|
+
<h1><%= t('Status') %></h1>
|
5
3
|
</div>
|
6
4
|
|
7
5
|
<div class="stats-wrapper">
|
@@ -29,11 +27,9 @@
|
|
29
27
|
</div>
|
30
28
|
</div>
|
31
29
|
|
32
|
-
<div class="
|
33
|
-
<
|
34
|
-
|
35
|
-
</div>
|
36
|
-
<div class="col-sm-3 pull-right flip">
|
30
|
+
<div class="header-container">
|
31
|
+
<h1><%= t('Processes') %></h1>
|
32
|
+
<div>
|
37
33
|
<form method="POST" class="warning-messages">
|
38
34
|
<%= csrf_tag %>
|
39
35
|
<div class="btn-group pull-right flip">
|
@@ -43,6 +39,7 @@
|
|
43
39
|
</form>
|
44
40
|
</div>
|
45
41
|
</div>
|
42
|
+
|
46
43
|
<div class="table_container">
|
47
44
|
<table class="processes table table-hover table-bordered table-striped">
|
48
45
|
<thead>
|
@@ -62,6 +59,9 @@
|
|
62
59
|
<% process.labels.each do |label| %>
|
63
60
|
<span class="label label-info"><%= label %></span>
|
64
61
|
<% end %>
|
62
|
+
<% if process.embedded? %>
|
63
|
+
<span class="label label-default">embedded</span>
|
64
|
+
<% end %>
|
65
65
|
<% if process.stopping? %>
|
66
66
|
<span class="label label-danger">quiet</span>
|
67
67
|
<% end %>
|
@@ -70,36 +70,47 @@
|
|
70
70
|
<% end %>
|
71
71
|
<br>
|
72
72
|
<b><%= "#{t('Queues')}: " %></b>
|
73
|
-
|
73
|
+
<% if process.weights %>
|
74
|
+
<%= busy_weights(process.weights) %>
|
75
|
+
<% else %>
|
76
|
+
<%= process.queues.sort.join(", ") %>
|
77
|
+
<% end %>
|
78
|
+
<% if process.version != Sidekiq::VERSION %>
|
79
|
+
<br>
|
80
|
+
<b><%= "#{t('Version')}: " %></b>
|
81
|
+
<% if process.version %>
|
82
|
+
<%= process.version %>
|
83
|
+
<% else %>
|
84
|
+
<%= t('Unknown') %>
|
85
|
+
<% end %>
|
86
|
+
<% end %>
|
74
87
|
</td>
|
75
88
|
<td><%= relative_time(Time.at(process['started_at'])) %></td>
|
76
89
|
<td><%= format_memory(process['rss'].to_i) %></td>
|
77
90
|
<td><%= process['concurrency'] %></td>
|
78
91
|
<td><%= process['busy'] %></td>
|
79
92
|
<td>
|
80
|
-
|
81
|
-
|
82
|
-
|
93
|
+
<% unless process.embedded? %>
|
94
|
+
<form method="POST">
|
95
|
+
<%= csrf_tag %>
|
96
|
+
<input type="hidden" name="identity" value="<%= process['identity'] %>"/>
|
83
97
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
98
|
+
<div class="btn-group pull-right flip">
|
99
|
+
<% unless process.stopping? %><button class="btn btn-xs btn-warn" type="submit" name="quiet" value="1"><%= t('Quiet') %></button><% end %>
|
100
|
+
<button class="btn btn-xs btn-danger" type="submit" name="stop" value="1"><%= t('Stop') %></button>
|
101
|
+
</div>
|
102
|
+
</form>
|
103
|
+
<% end %>
|
89
104
|
</td>
|
90
105
|
</tr>
|
91
106
|
<% end %>
|
92
107
|
</table>
|
93
108
|
</div>
|
94
109
|
|
95
|
-
<div class="
|
96
|
-
<
|
97
|
-
<h3><%= t('Jobs') %></h3>
|
98
|
-
</div>
|
110
|
+
<div class="header-container">
|
111
|
+
<h1><%= t('Jobs') %></h1>
|
99
112
|
<% if @workset.size > 0 && @total_size > @count %>
|
100
|
-
|
101
|
-
<%= erb :_paging, locals: { url: "#{root_path}busy" } %>
|
102
|
-
</div>
|
113
|
+
<%= erb :_paging, locals: { url: "#{root_path}busy" } %>
|
103
114
|
<% end %>
|
104
115
|
</div>
|
105
116
|
|
@@ -16,7 +16,7 @@
|
|
16
16
|
<% if job_result.totals["s"] > 0 %>
|
17
17
|
<div class="header-container">
|
18
18
|
<h1>
|
19
|
-
<a href="<%= root_path %>metrics"><%= t(
|
19
|
+
<a href="<%= root_path %>metrics"><%= t('Metrics') %></a> /
|
20
20
|
<%= h @name %>
|
21
21
|
</h1>
|
22
22
|
|
@@ -61,7 +61,7 @@
|
|
61
61
|
<p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p>
|
62
62
|
<% else %>
|
63
63
|
<h1>
|
64
|
-
<a href="<%= root_path %>/metrics"><%= t(
|
64
|
+
<a href="<%= root_path %>/metrics"><%= t('Metrics') %></a> /
|
65
65
|
<%= h @name %>
|
66
66
|
</h1>
|
67
67
|
|
data/web/views/morgue.erb
CHANGED
@@ -1,14 +1,10 @@
|
|
1
|
-
<
|
2
|
-
<
|
3
|
-
<h3><%= t('DeadJobs') %></h3>
|
4
|
-
</div>
|
1
|
+
<div class="header-container">
|
2
|
+
<h1><%= t('DeadJobs') %></h1>
|
5
3
|
<% if @dead.size > 0 && @total_size > @count %>
|
6
|
-
|
7
|
-
<%= erb :_paging, locals: { url: "#{root_path}morgue" } %>
|
8
|
-
</div>
|
4
|
+
<%= erb :_paging, locals: { url: "#{root_path}morgue" } %>
|
9
5
|
<% end %>
|
10
6
|
<%= filtering('dead') %>
|
11
|
-
</
|
7
|
+
</div>
|
12
8
|
|
13
9
|
<% if @dead.size > 0 %>
|
14
10
|
<form action="<%= root_path %>morgue" method="post">
|
@@ -33,7 +29,7 @@
|
|
33
29
|
<tr>
|
34
30
|
<td class="table-checkbox">
|
35
31
|
<label>
|
36
|
-
<input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' />
|
32
|
+
<input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' class='shift_clickable' />
|
37
33
|
</label>
|
38
34
|
</td>
|
39
35
|
<td>
|
data/web/views/queue.erb
CHANGED
@@ -1,17 +1,13 @@
|
|
1
|
-
<
|
2
|
-
<
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
<div class="col-sm-4 pull-right flip">
|
12
|
-
<%= erb :_paging, locals: { url: "#{root_path}queues/#{CGI.escape(@name)}" } %>
|
13
|
-
</div>
|
14
|
-
</header>
|
1
|
+
<div class="header-container">
|
2
|
+
<h1><%= t('CurrentMessagesInQueue', :queue => h(@name)) %>
|
3
|
+
<% if @queue.paused? %>
|
4
|
+
<span class="label label-danger"><%= t('Paused') %></span>
|
5
|
+
<% end %>
|
6
|
+
<span class="badge badge-secondary"><%= number_with_delimiter(@total_size) %></span>
|
7
|
+
</h1>
|
8
|
+
<%= erb :_paging, locals: { url: "#{root_path}queues/#{CGI.escape(@name)}" } %>
|
9
|
+
</div>
|
10
|
+
|
15
11
|
<div class="table_container">
|
16
12
|
<table class="queue table table-hover table-bordered table-striped">
|
17
13
|
<thead>
|
data/web/views/queues.erb
CHANGED
data/web/views/retries.erb
CHANGED
@@ -1,14 +1,10 @@
|
|
1
|
-
<
|
2
|
-
<
|
3
|
-
<h3><%= t('Retries') %></h3>
|
4
|
-
</div>
|
1
|
+
<div class="header-container">
|
2
|
+
<h1><%= t('Retries') %></h1>
|
5
3
|
<% if @retries.size > 0 && @total_size > @count %>
|
6
|
-
|
7
|
-
<%= erb :_paging, locals: { url: "#{root_path}retries" } %>
|
8
|
-
</div>
|
4
|
+
<%= erb :_paging, locals: { url: "#{root_path}retries" } %>
|
9
5
|
<% end %>
|
10
6
|
<%= filtering('retries') %>
|
11
|
-
</
|
7
|
+
</div>
|
12
8
|
|
13
9
|
<% if @retries.size > 0 %>
|
14
10
|
<form action="<%= root_path %>retries" method="post">
|
@@ -34,7 +30,7 @@
|
|
34
30
|
<tr>
|
35
31
|
<td class="table-checkbox">
|
36
32
|
<label>
|
37
|
-
<input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' />
|
33
|
+
<input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' class='shift_clickable' />
|
38
34
|
</label>
|
39
35
|
</td>
|
40
36
|
<td>
|
data/web/views/scheduled.erb
CHANGED
@@ -1,25 +1,22 @@
|
|
1
|
-
<
|
2
|
-
<
|
3
|
-
<h3><%= t('ScheduledJobs') %></h3>
|
4
|
-
</div>
|
1
|
+
<div class="header-container">
|
2
|
+
<h1><%= t('ScheduledJobs') %></h1>
|
5
3
|
<% if @scheduled.size > 0 && @total_size > @count %>
|
6
|
-
|
7
|
-
<%= erb :_paging, locals: { url: "#{root_path}scheduled" } %>
|
8
|
-
</div>
|
4
|
+
<%= erb :_paging, locals: { url: "#{root_path}scheduled" } %>
|
9
5
|
<% end %>
|
10
6
|
<%= filtering('scheduled') %>
|
11
|
-
</
|
7
|
+
</div>
|
12
8
|
|
13
9
|
<% if @scheduled.size > 0 %>
|
14
|
-
|
15
10
|
<form action="<%= root_path %>scheduled" method="post">
|
16
11
|
<%= csrf_tag %>
|
17
12
|
<div class="table_container">
|
18
13
|
<table class="table table-striped table-bordered table-hover">
|
19
14
|
<thead>
|
20
15
|
<tr>
|
21
|
-
<th class="checkbox-column">
|
22
|
-
<
|
16
|
+
<th class="table-checkbox checkbox-column">
|
17
|
+
<label>
|
18
|
+
<input type="checkbox" class="check_all" />
|
19
|
+
</label>
|
23
20
|
</th>
|
24
21
|
<th><%= t('When') %></th>
|
25
22
|
<th><%= t('Queue') %></th>
|
@@ -29,8 +26,10 @@
|
|
29
26
|
</thead>
|
30
27
|
<% @scheduled.each do |entry| %>
|
31
28
|
<tr>
|
32
|
-
<td>
|
33
|
-
<
|
29
|
+
<td class="table-checkbox">
|
30
|
+
<label>
|
31
|
+
<input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' class='shift_clickable' />
|
32
|
+
</label>
|
34
33
|
</td>
|
35
34
|
<td>
|
36
35
|
<a href="<%= root_path %>scheduled/<%= job_params(entry.item, entry.score) %>"><%= relative_time(entry.at) %></a>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.0.
|
4
|
+
version: 7.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Perham
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis-client
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.11.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.11.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: connection_pool
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -204,26 +204,14 @@ metadata:
|
|
204
204
|
documentation_uri: https://github.com/mperham/sidekiq/wiki
|
205
205
|
changelog_uri: https://github.com/mperham/sidekiq/blob/main/Changes.md
|
206
206
|
source_code_uri: https://github.com/mperham/sidekiq
|
207
|
-
post_install_message: |2
|
208
|
-
|
209
|
-
####################################################
|
210
|
-
|
211
|
-
|
212
|
-
█████████ █████ ██████████ ██████████ █████ ████ █████ ██████ ██████████ █████
|
213
|
-
███░░░░░███░░███ ░░███░░░░███ ░░███░░░░░█░░███ ███░ ░░███ ███░░░░███ ░███░░░░███ ███░░░███
|
214
|
-
░███ ░░░ ░███ ░███ ░░███ ░███ █ ░ ░███ ███ ░███ ███ ░░███ ░░░ ███ ███ ░░███
|
215
|
-
░░█████████ ░███ ░███ ░███ ░██████ ░███████ ░███ ░███ ░███ ███ ░███ ░███
|
216
|
-
░░░░░░░░███ ░███ ░███ ░███ ░███░░█ ░███░░███ ░███ ░███ ██░███ ███ ░███ ░███
|
217
|
-
███ ░███ ░███ ░███ ███ ░███ ░ █ ░███ ░░███ ░███ ░░███ ░░████ ███ ░░███ ███
|
218
|
-
░░█████████ █████ ██████████ ██████████ █████ ░░████ █████ ░░░██████░██ ███ ██ ░░░█████░
|
219
|
-
░░░░░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░ ░░░░░ ░░░░░░ ░░ ░░░ ░░ ░░░░░░
|
207
|
+
post_install_message: |2+
|
220
208
|
|
209
|
+
Welcome to Sidekiq 7.0!
|
221
210
|
|
222
211
|
1. Use `gem 'sidekiq', '<7'` in your Gemfile if you don't want this new version.
|
223
212
|
2. Read the release notes at https://github.com/mperham/sidekiq/blob/main/docs/7.0-Upgrade.md
|
224
|
-
3.
|
213
|
+
3. If you have problems, search for open/closed issues at https://github.com/mperham/sidekiq/issues/
|
225
214
|
|
226
|
-
####################################################
|
227
215
|
rdoc_options: []
|
228
216
|
require_paths:
|
229
217
|
- lib
|
@@ -243,3 +231,4 @@ signing_key:
|
|
243
231
|
specification_version: 4
|
244
232
|
summary: Simple, efficient background processing for Ruby
|
245
233
|
test_files: []
|
234
|
+
...
|