sidekiq 7.2.0 → 7.2.1
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 +13 -0
- data/bin/multi_queue_bench +268 -0
- data/lib/sidekiq/api.rb +57 -5
- data/lib/sidekiq/job_retry.rb +1 -2
- data/lib/sidekiq/metrics/query.rb +1 -0
- data/lib/sidekiq/metrics/tracking.rb +7 -3
- data/lib/sidekiq/rails.rb +3 -3
- data/lib/sidekiq/redis_connection.rb +2 -3
- data/lib/sidekiq/testing.rb +1 -1
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/csrf_protection.rb +6 -3
- data/sidekiq.gemspec +1 -1
- data/web/views/busy.erb +4 -4
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34d69bb09eb124a8fd4710af9972bdb6a0cd74429bc3e61cdccdae683a4a0203
|
4
|
+
data.tar.gz: 8a37c7f172e4efabb061f980a73547d7245585574133b07d159f0412e49dd362
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbb63070d419ad3d2b8192b2864ff4608288c00fe51c7e79e4a3faafd33665cce0c92ece38f9cd2a30ae4b7ff7e66debaf894198b054b88c5d0b5d5ee3790153
|
7
|
+
data.tar.gz: 8ba7a30ebdd19734a7cc64031a6eb63e4f317de0ae652bed324c272fd57f422186add097b38ab88aaa2a0a925de6b0845d18739691cbd9e9f2e90f3d79bb9e0a
|
data/Changes.md
CHANGED
@@ -2,6 +2,19 @@
|
|
2
2
|
|
3
3
|
[Sidekiq Changes](https://github.com/sidekiq/sidekiq/blob/main/Changes.md) | [Sidekiq Pro Changes](https://github.com/sidekiq/sidekiq/blob/main/Pro-Changes.md) | [Sidekiq Enterprise Changes](https://github.com/sidekiq/sidekiq/blob/main/Ent-Changes.md)
|
4
4
|
|
5
|
+
7.2.1
|
6
|
+
----------
|
7
|
+
|
8
|
+
- Add `Sidekiq::Work` type which replaces the raw Hash as the third parameter in
|
9
|
+
`Sidekiq::WorkSet#each { |pid, tid, hash| ... }` [#6145]
|
10
|
+
- **DEPRECATED**: direct access to the attributes within the `hash` block parameter above.
|
11
|
+
The `Sidekiq::Work` instance contains accessor methods to get at the same data, e.g.
|
12
|
+
```ruby
|
13
|
+
work["queue"] # Old
|
14
|
+
work.queue # New
|
15
|
+
```
|
16
|
+
- Fix Ruby 3.3 warnings around `base64` gem [#6151, earlopain]
|
17
|
+
|
5
18
|
7.2.0
|
6
19
|
----------
|
7
20
|
|
@@ -0,0 +1,268 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#
|
4
|
+
# bin/bench is a helpful script to load test and
|
5
|
+
# performance tune Sidekiq's core. It's a configurable script,
|
6
|
+
# which accepts the following parameters as ENV variables.
|
7
|
+
#
|
8
|
+
# QUEUES
|
9
|
+
# Number of queues to consume from. Default is 8
|
10
|
+
#
|
11
|
+
# PROCESSES
|
12
|
+
# The number of processes this benchmark will create. Each process, consumes
|
13
|
+
# from one of the available queues. When processes are more than the number of
|
14
|
+
# queues, they are distributed to processes in round robin. Default is 8
|
15
|
+
#
|
16
|
+
# ELEMENTS
|
17
|
+
# Number of jobs to push to each queue. Default is 1000
|
18
|
+
#
|
19
|
+
# ITERATIONS
|
20
|
+
# Each queue pushes ITERATIONS times ELEMENTS jobs. Default is 1000
|
21
|
+
#
|
22
|
+
# PORT
|
23
|
+
# The port of the Dragonfly instance. Default is 6379
|
24
|
+
#
|
25
|
+
# IP
|
26
|
+
# The ip of the Dragonfly instance. Default is 127.0.0.1
|
27
|
+
#
|
28
|
+
# Example Usage:
|
29
|
+
#
|
30
|
+
# > RUBY_YJIT_ENABLE=1 THREADS=10 PROCESSES=8 QUEUES=8 bin/multi_queue_bench
|
31
|
+
#
|
32
|
+
# None of this script is considered a public API and may change over time.
|
33
|
+
#
|
34
|
+
|
35
|
+
# Quiet some warnings we see when running in warning mode:
|
36
|
+
# RUBYOPT=-w bundle exec sidekiq
|
37
|
+
$TESTING = false
|
38
|
+
puts RUBY_DESCRIPTION
|
39
|
+
|
40
|
+
require "bundler/setup"
|
41
|
+
Bundler.require(:default, :load_test)
|
42
|
+
|
43
|
+
class LoadWorker
|
44
|
+
include Sidekiq::Job
|
45
|
+
sidekiq_options retry: 1
|
46
|
+
sidekiq_retry_in do |x|
|
47
|
+
1
|
48
|
+
end
|
49
|
+
|
50
|
+
def perform(idx, ts = nil)
|
51
|
+
puts(Time.now.to_f - ts) if !ts.nil?
|
52
|
+
# raise idx.to_s if idx % 100 == 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def Process.rss
|
57
|
+
`ps -o rss= -p #{Process.pid}`.chomp.to_i
|
58
|
+
end
|
59
|
+
|
60
|
+
$iterations = ENV["ITERATIONS"] ? Integer(ENV["ITERATIONS"]) : 1_000
|
61
|
+
$elements = ENV["ELEMENTS"] ? Integer(ENV["ELEMENTS"]) : 1_000
|
62
|
+
$port = ENV["PORT"] ? Integer(ENV["PORT"]) : 6379
|
63
|
+
$ip = ENV["IP"] ? String(ENV["IP"]) : "127.0.0.1"
|
64
|
+
|
65
|
+
class Loader
|
66
|
+
def initialize
|
67
|
+
@iter = $iterations
|
68
|
+
@count = $elements
|
69
|
+
end
|
70
|
+
|
71
|
+
def configure(queue)
|
72
|
+
@x = Sidekiq.configure_embed do |config|
|
73
|
+
config.redis = {db: 0, host: $ip, port: $port}
|
74
|
+
config.concurrency = Integer(ENV.fetch("THREADS", "30"))
|
75
|
+
config.queues = queue
|
76
|
+
config.logger.level = Logger::WARN
|
77
|
+
config.average_scheduled_poll_interval = 2
|
78
|
+
config.reliable! if defined?(Sidekiq::Pro)
|
79
|
+
end
|
80
|
+
|
81
|
+
@self_read, @self_write = IO.pipe
|
82
|
+
%w[INT TERM TSTP TTIN].each do |sig|
|
83
|
+
trap sig do
|
84
|
+
@self_write.puts(sig)
|
85
|
+
end
|
86
|
+
rescue ArgumentError
|
87
|
+
puts "Signal #{sig} not supported"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def handle_signal(sig)
|
92
|
+
launcher = @x
|
93
|
+
Sidekiq.logger.debug "Got #{sig} signal"
|
94
|
+
case sig
|
95
|
+
when "INT"
|
96
|
+
# Handle Ctrl-C in JRuby like MRI
|
97
|
+
# http://jira.codehaus.org/browse/JRUBY-4637
|
98
|
+
raise Interrupt
|
99
|
+
when "TERM"
|
100
|
+
# Heroku sends TERM and then waits 30 seconds for process to exit.
|
101
|
+
raise Interrupt
|
102
|
+
when "TSTP"
|
103
|
+
Sidekiq.logger.info "Received TSTP, no longer accepting new work"
|
104
|
+
launcher.quiet
|
105
|
+
when "TTIN"
|
106
|
+
Thread.list.each do |thread|
|
107
|
+
Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread["label"]}"
|
108
|
+
if thread.backtrace
|
109
|
+
Sidekiq.logger.warn thread.backtrace.join("\n")
|
110
|
+
else
|
111
|
+
Sidekiq.logger.warn "<no backtrace available>"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def setup(queue)
|
118
|
+
Sidekiq.logger.error("Setup RSS: #{Process.rss}")
|
119
|
+
Sidekiq.logger.error("Pushing work to queue: #{queue}")
|
120
|
+
start = Time.now
|
121
|
+
@iter.times do
|
122
|
+
arr = Array.new(@count) { |idx| [idx] }
|
123
|
+
#always prepends by queue:: that's why we pass 'q1, q2 etc' instead of `queue::q1`
|
124
|
+
Sidekiq::Client.push_bulk("class" => LoadWorker, "args" => arr, "queue" => queue)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def monitor_single(queue)
|
129
|
+
q = "queue:#{queue}"
|
130
|
+
@monitor_single = Thread.new do
|
131
|
+
GC.start
|
132
|
+
loop do
|
133
|
+
sleep 0.2
|
134
|
+
total = Sidekiq.redis do |conn|
|
135
|
+
conn.llen q
|
136
|
+
end
|
137
|
+
|
138
|
+
if total == 0
|
139
|
+
sleep 0.1
|
140
|
+
@x.stop
|
141
|
+
Process.kill("INT", $$)
|
142
|
+
break
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def monitor_all(queues)
|
150
|
+
@monitor_all = Thread.new do
|
151
|
+
GC.start
|
152
|
+
loop do
|
153
|
+
sleep 0.2
|
154
|
+
qsize = 0
|
155
|
+
queues.each do |q|
|
156
|
+
tmp = Sidekiq.redis do |conn|
|
157
|
+
conn.llen q
|
158
|
+
end
|
159
|
+
qsize = qsize + tmp
|
160
|
+
end
|
161
|
+
total = qsize
|
162
|
+
|
163
|
+
if total == 0
|
164
|
+
ending = Time.now - @start
|
165
|
+
size = @iter * @count * queues.length()
|
166
|
+
Sidekiq.logger.error("Done, #{size} jobs in #{ending} sec, #{(size / ending).to_i} jobs/sec")
|
167
|
+
Sidekiq.logger.error("Ending RSS: #{Process.rss}")
|
168
|
+
|
169
|
+
sleep 0.1
|
170
|
+
@x.stop
|
171
|
+
Process.kill("INT", $$)
|
172
|
+
break
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def run(queues, queue, monitor_all_queues)
|
179
|
+
#Sidekiq.logger.warn("Consuming from #{queue}")
|
180
|
+
if monitor_all_queues
|
181
|
+
monitor_all(queues)
|
182
|
+
else
|
183
|
+
monitor_single(queue)
|
184
|
+
end
|
185
|
+
|
186
|
+
@start = Time.now
|
187
|
+
@x.run
|
188
|
+
|
189
|
+
while (readable_io = IO.select([@self_read]))
|
190
|
+
signal = readable_io.first[0].gets.strip
|
191
|
+
handle_signal(signal)
|
192
|
+
end
|
193
|
+
# normal
|
194
|
+
rescue Interrupt
|
195
|
+
rescue => e
|
196
|
+
raise e if $DEBUG
|
197
|
+
warn e.message
|
198
|
+
warn e.backtrace.join("\n")
|
199
|
+
exit 1
|
200
|
+
ensure
|
201
|
+
@x.stop
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def setup(queue)
|
206
|
+
ll = Loader.new
|
207
|
+
ll.configure(queue)
|
208
|
+
ll.setup(queue)
|
209
|
+
end
|
210
|
+
|
211
|
+
def consume(queues, queue, monitor_all_queues)
|
212
|
+
ll = Loader.new
|
213
|
+
ll.configure(queue)
|
214
|
+
ll.run(queues, queue, monitor_all_queues)
|
215
|
+
end
|
216
|
+
|
217
|
+
# We assign one queue to each sidekiq process
|
218
|
+
def run(number_of_processes, total_queues)
|
219
|
+
read_stream, write_stream = IO.pipe
|
220
|
+
|
221
|
+
queues = []
|
222
|
+
(0..total_queues-1).each do |idx|
|
223
|
+
queues.push("queue:q#{idx}")
|
224
|
+
end
|
225
|
+
|
226
|
+
Sidekiq.logger.info("Queues are: #{queues}")
|
227
|
+
|
228
|
+
# Produce
|
229
|
+
start = Time.now
|
230
|
+
(0..total_queues-1).each do |idx|
|
231
|
+
Process.fork do
|
232
|
+
queue_num = "q#{idx}"
|
233
|
+
setup(queue_num)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
queue_sz = $iterations * $elements * total_queues
|
238
|
+
Process.waitall
|
239
|
+
|
240
|
+
ending = Time.now - start
|
241
|
+
#Sidekiq.logger.info("Pushed #{queue_sz} in #{ending} secs")
|
242
|
+
|
243
|
+
# Consume
|
244
|
+
(0..number_of_processes-1).each do |idx|
|
245
|
+
Process.fork do
|
246
|
+
# First process only consumes from it's own queue but monitors all queues.
|
247
|
+
# It works as a synchronization point. Once all processes finish
|
248
|
+
# (that is, when all queues are emptied) it prints the the stats.
|
249
|
+
if idx == 0
|
250
|
+
queue = "q#{idx}"
|
251
|
+
consume(queues, queue, true)
|
252
|
+
else
|
253
|
+
queue = "q#{idx % total_queues}"
|
254
|
+
consume(queues, queue, false)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
Process.waitall
|
260
|
+
write_stream.close
|
261
|
+
results = read_stream.read
|
262
|
+
read_stream.close
|
263
|
+
end
|
264
|
+
|
265
|
+
$total_processes = ENV["PROCESSES"] ? Integer(ENV["PROCESSES"]) : 8;
|
266
|
+
$total_queues = ENV["QUEUES"] ? Integer(ENV["QUEUES"]) : 8;
|
267
|
+
|
268
|
+
run($total_processes, $total_queues)
|
data/lib/sidekiq/api.rb
CHANGED
@@ -4,7 +4,6 @@ require "sidekiq"
|
|
4
4
|
|
5
5
|
require "zlib"
|
6
6
|
require "set"
|
7
|
-
require "base64"
|
8
7
|
|
9
8
|
require "sidekiq/metrics/query"
|
10
9
|
|
@@ -491,8 +490,8 @@ module Sidekiq
|
|
491
490
|
end
|
492
491
|
|
493
492
|
def uncompress_backtrace(backtrace)
|
494
|
-
|
495
|
-
uncompressed = Zlib::Inflate.inflate(
|
493
|
+
strict_base64_decoded = backtrace.unpack1("m0")
|
494
|
+
uncompressed = Zlib::Inflate.inflate(strict_base64_decoded)
|
496
495
|
Sidekiq.load_json(uncompressed)
|
497
496
|
end
|
498
497
|
end
|
@@ -1110,11 +1109,11 @@ module Sidekiq
|
|
1110
1109
|
|
1111
1110
|
procs.zip(all_works).each do |key, workers|
|
1112
1111
|
workers.each_pair do |tid, json|
|
1113
|
-
results << [key, tid, Sidekiq.load_json(json)] unless json.empty?
|
1112
|
+
results << [key, tid, Sidekiq::Work.new(key, tid, Sidekiq.load_json(json))] unless json.empty?
|
1114
1113
|
end
|
1115
1114
|
end
|
1116
1115
|
|
1117
|
-
results.sort_by { |(_, _, hsh)| hsh
|
1116
|
+
results.sort_by { |(_, _, hsh)| hsh.raw("run_at") }.each(&block)
|
1118
1117
|
end
|
1119
1118
|
|
1120
1119
|
# Note that #size is only as accurate as Sidekiq's heartbeat,
|
@@ -1138,6 +1137,59 @@ module Sidekiq
|
|
1138
1137
|
end
|
1139
1138
|
end
|
1140
1139
|
end
|
1140
|
+
|
1141
|
+
# Sidekiq::Work represents a job which is currently executing.
|
1142
|
+
class Work
|
1143
|
+
attr_reader :process_id
|
1144
|
+
attr_reader :thread_id
|
1145
|
+
|
1146
|
+
def initialize(pid, tid, hsh)
|
1147
|
+
@process_id = pid
|
1148
|
+
@thread_id = tid
|
1149
|
+
@hsh = hsh
|
1150
|
+
@job = nil
|
1151
|
+
end
|
1152
|
+
|
1153
|
+
def queue
|
1154
|
+
@hsh["queue"]
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
def run_at
|
1158
|
+
Time.at(@hsh["run_at"])
|
1159
|
+
end
|
1160
|
+
|
1161
|
+
def job
|
1162
|
+
@job ||= Sidekiq::JobRecord.new(@hsh["payload"])
|
1163
|
+
end
|
1164
|
+
|
1165
|
+
def payload
|
1166
|
+
@hsh["payload"]
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
# deprecated
|
1170
|
+
def [](key)
|
1171
|
+
kwargs = {uplevel: 1}
|
1172
|
+
kwargs[:category] = :deprecated if RUBY_VERSION > "3.0" # TODO
|
1173
|
+
warn("Direct access to `Sidekiq::Work` attributes is deprecated, please use `#payload`, `#queue`, `#run_at` or `#job` instead", **kwargs)
|
1174
|
+
|
1175
|
+
@hsh[key]
|
1176
|
+
end
|
1177
|
+
|
1178
|
+
# :nodoc:
|
1179
|
+
# @api private
|
1180
|
+
def raw(name)
|
1181
|
+
@hsh[name]
|
1182
|
+
end
|
1183
|
+
|
1184
|
+
def method_missing(*all)
|
1185
|
+
@hsh.send(*all)
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
def respond_to_missing?(name)
|
1189
|
+
@hsh.respond_to?(name)
|
1190
|
+
end
|
1191
|
+
end
|
1192
|
+
|
1141
1193
|
# Since "worker" is a nebulous term, we've deprecated the use of this class name.
|
1142
1194
|
# Is "worker" a process, a type of job, a thread? Undefined!
|
1143
1195
|
# WorkSet better describes the data.
|
data/lib/sidekiq/job_retry.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "zlib"
|
4
|
-
require "base64"
|
5
4
|
require "sidekiq/component"
|
6
5
|
|
7
6
|
module Sidekiq
|
@@ -295,7 +294,7 @@ module Sidekiq
|
|
295
294
|
def compress_backtrace(backtrace)
|
296
295
|
serialized = Sidekiq.dump_json(backtrace)
|
297
296
|
compressed = Zlib::Deflate.deflate(serialized)
|
298
|
-
|
297
|
+
[compressed].pack("m0") # Base64.strict_encode64
|
299
298
|
end
|
300
299
|
end
|
301
300
|
end
|
@@ -103,12 +103,16 @@ module Sidekiq
|
|
103
103
|
def reset
|
104
104
|
@lock.synchronize {
|
105
105
|
array = [@totals, @jobs, @grams]
|
106
|
-
|
107
|
-
@jobs = Hash.new(0)
|
108
|
-
@grams = Hash.new { |hash, key| hash[key] = Histogram.new(key) }
|
106
|
+
reset_instance_variables
|
109
107
|
array
|
110
108
|
}
|
111
109
|
end
|
110
|
+
|
111
|
+
def reset_instance_variables
|
112
|
+
@totals = Hash.new(0)
|
113
|
+
@jobs = Hash.new(0)
|
114
|
+
@grams = Hash.new { |hash, key| hash[key] = Histogram.new(key) }
|
115
|
+
end
|
112
116
|
end
|
113
117
|
|
114
118
|
class Middleware
|
data/lib/sidekiq/rails.rb
CHANGED
@@ -56,10 +56,10 @@ module Sidekiq
|
|
56
56
|
# This is the integration code necessary so that if a job uses `Rails.logger.info "Hello"`,
|
57
57
|
# it will appear in the Sidekiq console with all of the job context.
|
58
58
|
unless ::Rails.logger == config.logger || ::ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, $stdout)
|
59
|
-
if ::Rails
|
60
|
-
::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
|
61
|
-
else
|
59
|
+
if ::Rails.logger.respond_to?(:broadcast_to)
|
62
60
|
::Rails.logger.broadcast_to(config.logger)
|
61
|
+
else
|
62
|
+
::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
@@ -39,9 +39,8 @@ module Sidekiq
|
|
39
39
|
uri.password = redacted
|
40
40
|
scrubbed_options[:url] = uri.to_s
|
41
41
|
end
|
42
|
-
if scrubbed_options[:password]
|
43
|
-
|
44
|
-
end
|
42
|
+
scrubbed_options[:password] = redacted if scrubbed_options[:password]
|
43
|
+
scrubbed_options[:sentinel_password] = redacted if scrubbed_options[:sentinel_password]
|
45
44
|
scrubbed_options[:sentinels]&.each do |sentinel|
|
46
45
|
sentinel[:password] = redacted if sentinel[:password]
|
47
46
|
end
|
data/lib/sidekiq/testing.rb
CHANGED
@@ -278,7 +278,7 @@ module Sidekiq
|
|
278
278
|
def perform_one
|
279
279
|
raise(EmptyQueueError, "perform_one called with empty job queue") if jobs.empty?
|
280
280
|
next_job = jobs.first
|
281
|
-
Queues.delete_for(next_job["jid"], queue, to_s)
|
281
|
+
Queues.delete_for(next_job["jid"], next_job["queue"], to_s)
|
282
282
|
process_job(next_job)
|
283
283
|
end
|
284
284
|
|
data/lib/sidekiq/version.rb
CHANGED
@@ -27,7 +27,6 @@
|
|
27
27
|
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
28
28
|
|
29
29
|
require "securerandom"
|
30
|
-
require "base64"
|
31
30
|
require "rack/request"
|
32
31
|
|
33
32
|
module Sidekiq
|
@@ -143,7 +142,7 @@ module Sidekiq
|
|
143
142
|
one_time_pad = SecureRandom.random_bytes(token.length)
|
144
143
|
encrypted_token = xor_byte_strings(one_time_pad, token)
|
145
144
|
masked_token = one_time_pad + encrypted_token
|
146
|
-
|
145
|
+
encode_token(masked_token)
|
147
146
|
end
|
148
147
|
|
149
148
|
# Essentially the inverse of +mask_token+.
|
@@ -168,8 +167,12 @@ module Sidekiq
|
|
168
167
|
::Rack::Utils.secure_compare(token.to_s, decode_token(local).to_s)
|
169
168
|
end
|
170
169
|
|
170
|
+
def encode_token(token)
|
171
|
+
[token].pack("m0").tr("+/", "-_")
|
172
|
+
end
|
173
|
+
|
171
174
|
def decode_token(token)
|
172
|
-
|
175
|
+
token.tr("-_", "+/").unpack1("m0")
|
173
176
|
end
|
174
177
|
|
175
178
|
def xor_byte_strings(s1, s2)
|
data/sidekiq.gemspec
CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |gem|
|
|
23
23
|
"rubygems_mfa_required" => "true"
|
24
24
|
}
|
25
25
|
|
26
|
-
gem.add_dependency "redis-client", ">= 0.
|
26
|
+
gem.add_dependency "redis-client", ">= 0.19.0"
|
27
27
|
gem.add_dependency "connection_pool", ">= 2.3.0"
|
28
28
|
gem.add_dependency "rack", ">= 2.2.4"
|
29
29
|
gem.add_dependency "concurrent-ruby", "< 2"
|
data/web/views/busy.erb
CHANGED
@@ -125,14 +125,14 @@
|
|
125
125
|
<th><%= t('Arguments') %></th>
|
126
126
|
<th><%= t('Started') %></th>
|
127
127
|
</thead>
|
128
|
-
<% @workset.each do |process, thread,
|
129
|
-
<% job =
|
128
|
+
<% @workset.each do |process, thread, work| %>
|
129
|
+
<% job = work.job %>
|
130
130
|
<tr>
|
131
131
|
<td><%= process %></td>
|
132
132
|
<td><%= thread %></td>
|
133
133
|
<td><%= job.jid %></td>
|
134
134
|
<td>
|
135
|
-
<a href="<%= root_path %>queues/<%=
|
135
|
+
<a href="<%= root_path %>queues/<%= work.queue %>"><%= work.queue %></a>
|
136
136
|
</td>
|
137
137
|
<td>
|
138
138
|
<%= job.display_class %>
|
@@ -141,7 +141,7 @@
|
|
141
141
|
<td>
|
142
142
|
<div class="args"><%= display_args(job.display_args) %></div>
|
143
143
|
</td>
|
144
|
-
<td><%= relative_time(
|
144
|
+
<td><%= relative_time(work.run_at) %></td>
|
145
145
|
</tr>
|
146
146
|
<% end %>
|
147
147
|
</table>
|
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.2.
|
4
|
+
version: 7.2.1
|
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: 2024-01-19 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.19.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.19.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: connection_pool
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -78,6 +78,7 @@ files:
|
|
78
78
|
- Changes.md
|
79
79
|
- LICENSE.txt
|
80
80
|
- README.md
|
81
|
+
- bin/multi_queue_bench
|
81
82
|
- bin/sidekiq
|
82
83
|
- bin/sidekiqload
|
83
84
|
- bin/sidekiqmon
|