sidekiq 5.2.5 → 6.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/.circleci/config.yml +82 -0
- data/.gitignore +0 -2
- data/.standard.yml +20 -0
- data/6.0-Upgrade.md +72 -0
- data/COMM-LICENSE +11 -9
- data/Changes.md +136 -0
- data/Ent-2.0-Upgrade.md +37 -0
- data/Ent-Changes.md +32 -1
- data/Gemfile +12 -17
- data/Gemfile.lock +196 -0
- data/Pro-5.0-Upgrade.md +25 -0
- data/Pro-Changes.md +26 -2
- data/README.md +19 -31
- data/Rakefile +5 -4
- data/bin/sidekiqload +33 -25
- data/bin/sidekiqmon +8 -0
- data/lib/generators/sidekiq/templates/worker_test.rb.erb +1 -1
- data/lib/generators/sidekiq/worker_generator.rb +20 -12
- data/lib/sidekiq/api.rb +230 -214
- data/lib/sidekiq/cli.rb +111 -174
- data/lib/sidekiq/client.rb +55 -46
- data/lib/sidekiq/delay.rb +5 -6
- data/lib/sidekiq/exception_handler.rb +10 -12
- data/lib/sidekiq/extensions/action_mailer.rb +10 -20
- data/lib/sidekiq/extensions/active_record.rb +9 -7
- data/lib/sidekiq/extensions/class_methods.rb +9 -7
- data/lib/sidekiq/extensions/generic_proxy.rb +4 -4
- data/lib/sidekiq/fetch.rb +11 -12
- data/lib/sidekiq/job_logger.rb +45 -7
- data/lib/sidekiq/job_retry.rb +71 -60
- data/lib/sidekiq/launcher.rb +57 -51
- data/lib/sidekiq/logger.rb +165 -0
- data/lib/sidekiq/manager.rb +7 -9
- data/lib/sidekiq/middleware/chain.rb +14 -4
- data/lib/sidekiq/middleware/i18n.rb +5 -7
- data/lib/sidekiq/monitor.rb +133 -0
- data/lib/sidekiq/paginator.rb +18 -14
- data/lib/sidekiq/processor.rb +83 -75
- data/lib/sidekiq/rails.rb +23 -29
- data/lib/sidekiq/redis_connection.rb +31 -37
- data/lib/sidekiq/scheduled.rb +28 -29
- data/lib/sidekiq/testing/inline.rb +2 -1
- data/lib/sidekiq/testing.rb +34 -23
- data/lib/sidekiq/util.rb +17 -16
- data/lib/sidekiq/version.rb +2 -1
- data/lib/sidekiq/web/action.rb +14 -10
- data/lib/sidekiq/web/application.rb +64 -66
- data/lib/sidekiq/web/helpers.rb +89 -71
- data/lib/sidekiq/web/router.rb +17 -14
- data/lib/sidekiq/web.rb +41 -49
- data/lib/sidekiq/worker.rb +129 -97
- data/lib/sidekiq.rb +61 -42
- data/sidekiq.gemspec +16 -16
- data/web/assets/javascripts/dashboard.js +4 -23
- data/web/assets/stylesheets/application-dark.css +125 -0
- data/web/assets/stylesheets/application.css +9 -0
- data/web/assets/stylesheets/bootstrap.css +1 -1
- data/web/locales/de.yml +14 -2
- data/web/locales/ja.yml +2 -1
- data/web/views/_job_info.erb +2 -1
- data/web/views/busy.erb +4 -1
- data/web/views/dead.erb +2 -2
- data/web/views/layout.erb +1 -0
- data/web/views/morgue.erb +4 -1
- data/web/views/queue.erb +10 -1
- data/web/views/queues.erb +1 -1
- data/web/views/retries.erb +4 -1
- data/web/views/retry.erb +2 -2
- data/web/views/scheduled.erb +4 -1
- metadata +21 -32
- data/.travis.yml +0 -17
- data/Appraisals +0 -9
- data/bin/sidekiqctl +0 -237
- data/gemfiles/rails_4.gemfile +0 -31
- data/gemfiles/rails_5.gemfile +0 -31
- data/lib/sidekiq/core_ext.rb +0 -1
- data/lib/sidekiq/logging.rb +0 -122
- data/lib/sidekiq/middleware/server/active_record.rb +0 -23
@@ -5,8 +5,7 @@ module Sidekiq
|
|
5
5
|
extend WebRouter
|
6
6
|
|
7
7
|
CONTENT_LENGTH = "Content-Length"
|
8
|
-
|
9
|
-
REDIS_KEYS = %w(redis_version uptime_in_days connected_clients used_memory_human used_memory_peak_human)
|
8
|
+
REDIS_KEYS = %w[redis_version uptime_in_days connected_clients used_memory_human used_memory_peak_human]
|
10
9
|
CSP_HEADER = [
|
11
10
|
"default-src 'self' https: http:",
|
12
11
|
"child-src 'self'",
|
@@ -20,8 +19,8 @@ module Sidekiq
|
|
20
19
|
"script-src 'self' https: http: 'unsafe-inline'",
|
21
20
|
"style-src 'self' https: http: 'unsafe-inline'",
|
22
21
|
"worker-src 'self'",
|
23
|
-
"base-uri 'self'"
|
24
|
-
].join(
|
22
|
+
"base-uri 'self'",
|
23
|
+
].join("; ").freeze
|
25
24
|
|
26
25
|
def initialize(klass)
|
27
26
|
@klass = klass
|
@@ -44,8 +43,8 @@ module Sidekiq
|
|
44
43
|
end
|
45
44
|
|
46
45
|
get "/" do
|
47
|
-
@redis_info = redis_info.select{ |k, v| REDIS_KEYS.include? k }
|
48
|
-
stats_history = Sidekiq::Stats::History.new((params[
|
46
|
+
@redis_info = redis_info.select { |k, v| REDIS_KEYS.include? k }
|
47
|
+
stats_history = Sidekiq::Stats::History.new((params["days"] || 30).to_i)
|
49
48
|
@processed_history = stats_history.processed
|
50
49
|
@failed_history = stats_history.failed
|
51
50
|
|
@@ -57,14 +56,14 @@ module Sidekiq
|
|
57
56
|
end
|
58
57
|
|
59
58
|
post "/busy" do
|
60
|
-
if params[
|
61
|
-
p = Sidekiq::Process.new(
|
62
|
-
p.quiet! if params[
|
63
|
-
p.stop! if params[
|
59
|
+
if params["identity"]
|
60
|
+
p = Sidekiq::Process.new("identity" => params["identity"])
|
61
|
+
p.quiet! if params["quiet"]
|
62
|
+
p.stop! if params["stop"]
|
64
63
|
else
|
65
64
|
processes.each do |pro|
|
66
|
-
pro.quiet! if params[
|
67
|
-
pro.stop! if params[
|
65
|
+
pro.quiet! if params["quiet"]
|
66
|
+
pro.stop! if params["stop"]
|
68
67
|
end
|
69
68
|
end
|
70
69
|
|
@@ -82,9 +81,9 @@ module Sidekiq
|
|
82
81
|
|
83
82
|
halt(404) unless @name
|
84
83
|
|
85
|
-
@count = (params[
|
84
|
+
@count = (params["count"] || 25).to_i
|
86
85
|
@queue = Sidekiq::Queue.new(@name)
|
87
|
-
(@current_page, @total_size, @messages) = page("queue:#{@name}", params[
|
86
|
+
(@current_page, @total_size, @messages) = page("queue:#{@name}", params["page"], @count, reverse: params["direction"] == "asc")
|
88
87
|
@messages = @messages.map { |msg| Sidekiq::Job.new(msg, @name) }
|
89
88
|
|
90
89
|
erb(:queue)
|
@@ -98,21 +97,22 @@ module Sidekiq
|
|
98
97
|
|
99
98
|
post "/queues/:name/delete" do
|
100
99
|
name = route_params[:name]
|
101
|
-
Sidekiq::Job.new(params[
|
100
|
+
Sidekiq::Job.new(params["key_val"], name).delete
|
102
101
|
|
103
102
|
redirect_with_query("#{root_path}queues/#{CGI.escape(name)}")
|
104
103
|
end
|
105
104
|
|
106
|
-
get
|
107
|
-
@count = (params[
|
108
|
-
(@current_page, @total_size, @dead) = page("dead", params[
|
105
|
+
get "/morgue" do
|
106
|
+
@count = (params["count"] || 25).to_i
|
107
|
+
(@current_page, @total_size, @dead) = page("dead", params["page"], @count, reverse: true)
|
109
108
|
@dead = @dead.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
110
109
|
|
111
110
|
erb(:morgue)
|
112
111
|
end
|
113
112
|
|
114
113
|
get "/morgue/:key" do
|
115
|
-
|
114
|
+
key = route_params[:key]
|
115
|
+
halt(404) unless key
|
116
116
|
|
117
117
|
@dead = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
|
118
118
|
|
@@ -123,10 +123,10 @@ module Sidekiq
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
-
post
|
127
|
-
redirect(request.path) unless params[
|
126
|
+
post "/morgue" do
|
127
|
+
redirect(request.path) unless params["key"]
|
128
128
|
|
129
|
-
params[
|
129
|
+
params["key"].each do |key|
|
130
130
|
job = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
|
131
131
|
retry_or_delete_or_kill job, params if job
|
132
132
|
end
|
@@ -147,7 +147,8 @@ module Sidekiq
|
|
147
147
|
end
|
148
148
|
|
149
149
|
post "/morgue/:key" do
|
150
|
-
|
150
|
+
key = route_params[:key]
|
151
|
+
halt(404) unless key
|
151
152
|
|
152
153
|
job = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
|
153
154
|
retry_or_delete_or_kill job, params if job
|
@@ -155,9 +156,9 @@ module Sidekiq
|
|
155
156
|
redirect_with_query("#{root_path}morgue")
|
156
157
|
end
|
157
158
|
|
158
|
-
get
|
159
|
-
@count = (params[
|
160
|
-
(@current_page, @total_size, @retries) = page("retry", params[
|
159
|
+
get "/retries" do
|
160
|
+
@count = (params["count"] || 25).to_i
|
161
|
+
(@current_page, @total_size, @retries) = page("retry", params["page"], @count)
|
161
162
|
@retries = @retries.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
162
163
|
|
163
164
|
erb(:retries)
|
@@ -173,10 +174,10 @@ module Sidekiq
|
|
173
174
|
end
|
174
175
|
end
|
175
176
|
|
176
|
-
post
|
177
|
-
redirect(request.path) unless params[
|
177
|
+
post "/retries" do
|
178
|
+
redirect(request.path) unless params["key"]
|
178
179
|
|
179
|
-
params[
|
180
|
+
params["key"].each do |key|
|
180
181
|
job = Sidekiq::RetrySet.new.fetch(*parse_params(key)).first
|
181
182
|
retry_or_delete_or_kill job, params if job
|
182
183
|
end
|
@@ -210,9 +211,9 @@ module Sidekiq
|
|
210
211
|
redirect_with_query("#{root_path}retries")
|
211
212
|
end
|
212
213
|
|
213
|
-
get
|
214
|
-
@count = (params[
|
215
|
-
(@current_page, @total_size, @scheduled) = page("schedule", params[
|
214
|
+
get "/scheduled" do
|
215
|
+
@count = (params["count"] || 25).to_i
|
216
|
+
(@current_page, @total_size, @scheduled) = page("schedule", params["page"], @count)
|
216
217
|
@scheduled = @scheduled.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
217
218
|
|
218
219
|
erb(:scheduled)
|
@@ -228,10 +229,10 @@ module Sidekiq
|
|
228
229
|
end
|
229
230
|
end
|
230
231
|
|
231
|
-
post
|
232
|
-
redirect(request.path) unless params[
|
232
|
+
post "/scheduled" do
|
233
|
+
redirect(request.path) unless params["key"]
|
233
234
|
|
234
|
-
params[
|
235
|
+
params["key"].each do |key|
|
235
236
|
job = Sidekiq::ScheduledSet.new.fetch(*parse_params(key)).first
|
236
237
|
delete_or_add_queue job, params if job
|
237
238
|
end
|
@@ -240,7 +241,8 @@ module Sidekiq
|
|
240
241
|
end
|
241
242
|
|
242
243
|
post "/scheduled/:key" do
|
243
|
-
|
244
|
+
key = route_params[:key]
|
245
|
+
halt(404) unless key
|
244
246
|
|
245
247
|
job = Sidekiq::ScheduledSet.new.fetch(*parse_params(key)).first
|
246
248
|
delete_or_add_queue job, params if job
|
@@ -248,48 +250,44 @@ module Sidekiq
|
|
248
250
|
redirect_with_query("#{root_path}scheduled")
|
249
251
|
end
|
250
252
|
|
251
|
-
get
|
253
|
+
get "/dashboard/stats" do
|
252
254
|
redirect "#{root_path}stats"
|
253
255
|
end
|
254
256
|
|
255
|
-
get
|
257
|
+
get "/stats" do
|
256
258
|
sidekiq_stats = Sidekiq::Stats.new
|
257
|
-
redis_stats
|
259
|
+
redis_stats = redis_info.select { |k, v| REDIS_KEYS.include? k }
|
258
260
|
json(
|
259
261
|
sidekiq: {
|
260
|
-
processed:
|
261
|
-
failed:
|
262
|
-
busy:
|
263
|
-
processes:
|
264
|
-
enqueued:
|
265
|
-
scheduled:
|
266
|
-
retries:
|
267
|
-
dead:
|
268
|
-
default_latency: sidekiq_stats.default_queue_latency
|
262
|
+
processed: sidekiq_stats.processed,
|
263
|
+
failed: sidekiq_stats.failed,
|
264
|
+
busy: sidekiq_stats.workers_size,
|
265
|
+
processes: sidekiq_stats.processes_size,
|
266
|
+
enqueued: sidekiq_stats.enqueued,
|
267
|
+
scheduled: sidekiq_stats.scheduled_size,
|
268
|
+
retries: sidekiq_stats.retry_size,
|
269
|
+
dead: sidekiq_stats.dead_size,
|
270
|
+
default_latency: sidekiq_stats.default_queue_latency,
|
269
271
|
},
|
270
272
|
redis: redis_stats,
|
271
273
|
server_utc_time: server_utc_time
|
272
274
|
)
|
273
275
|
end
|
274
276
|
|
275
|
-
get
|
277
|
+
get "/stats/queues" do
|
276
278
|
json Sidekiq::Stats::Queues.new.lengths
|
277
279
|
end
|
278
280
|
|
279
281
|
def call(env)
|
280
282
|
action = self.class.match(env)
|
281
|
-
return [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"
|
283
|
+
return [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found"]] unless action
|
282
284
|
|
283
|
-
|
284
|
-
|
285
|
+
app = @klass
|
286
|
+
resp = catch(:halt) do # rubocop:disable Standard/SemanticBlocks
|
285
287
|
self.class.run_befores(app, action)
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
self.class.run_afters(app, action)
|
290
|
-
end
|
291
|
-
|
292
|
-
resp
|
288
|
+
action.instance_exec env, &action.block
|
289
|
+
ensure
|
290
|
+
self.class.run_afters(app, action)
|
293
291
|
end
|
294
292
|
|
295
293
|
resp = case resp
|
@@ -300,7 +298,7 @@ module Sidekiq
|
|
300
298
|
"Content-Type" => "text/html",
|
301
299
|
"Cache-Control" => "no-cache",
|
302
300
|
"Content-Language" => action.locale,
|
303
|
-
"Content-Security-Policy" => CSP_HEADER
|
301
|
+
"Content-Security-Policy" => CSP_HEADER,
|
304
302
|
}
|
305
303
|
|
306
304
|
[200, headers, [resp]]
|
@@ -308,12 +306,12 @@ module Sidekiq
|
|
308
306
|
|
309
307
|
resp[1] = resp[1].dup
|
310
308
|
|
311
|
-
resp[1][CONTENT_LENGTH] = resp[2].
|
309
|
+
resp[1][CONTENT_LENGTH] = resp[2].sum(&:bytesize).to_s
|
312
310
|
|
313
311
|
resp
|
314
312
|
end
|
315
313
|
|
316
|
-
def self.helpers(mod=nil, &block)
|
314
|
+
def self.helpers(mod = nil, &block)
|
317
315
|
if block_given?
|
318
316
|
WebAction.class_eval(&block)
|
319
317
|
else
|
@@ -321,11 +319,11 @@ module Sidekiq
|
|
321
319
|
end
|
322
320
|
end
|
323
321
|
|
324
|
-
def self.before(path=nil, &block)
|
322
|
+
def self.before(path = nil, &block)
|
325
323
|
befores << [path && Regexp.new("\\A#{path.gsub("*", ".*")}\\z"), block]
|
326
324
|
end
|
327
325
|
|
328
|
-
def self.after(path=nil, &block)
|
326
|
+
def self.after(path = nil, &block)
|
329
327
|
afters << [path && Regexp.new("\\A#{path.gsub("*", ".*")}\\z"), block]
|
330
328
|
end
|
331
329
|
|
@@ -338,8 +336,8 @@ module Sidekiq
|
|
338
336
|
end
|
339
337
|
|
340
338
|
def self.run_hooks(hooks, app, action)
|
341
|
-
hooks.select { |p,_| !p || p =~ action.env[WebRouter::PATH_INFO] }
|
342
|
-
|
339
|
+
hooks.select { |p, _| !p || p =~ action.env[WebRouter::PATH_INFO] }
|
340
|
+
.each { |_, b| action.instance_exec(action.env, app, &b) }
|
343
341
|
end
|
344
342
|
|
345
343
|
def self.befores
|
data/lib/sidekiq/web/helpers.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
2
|
+
|
3
|
+
require "uri"
|
4
|
+
require "set"
|
5
|
+
require "yaml"
|
6
|
+
require "cgi"
|
6
7
|
|
7
8
|
module Sidekiq
|
8
9
|
# This is not a public API
|
9
10
|
module WebHelpers
|
10
11
|
def strings(lang)
|
11
|
-
|
12
|
-
|
12
|
+
@strings ||= {}
|
13
|
+
@strings[lang] ||= begin
|
13
14
|
# Allow sidekiq-web extensions to add locale paths
|
14
15
|
# so extensions can be localized
|
15
16
|
settings.locales.each_with_object({}) do |path, global|
|
@@ -22,19 +23,19 @@ module Sidekiq
|
|
22
23
|
end
|
23
24
|
|
24
25
|
def clear_caches
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
@strings = nil
|
27
|
+
@locale_files = nil
|
28
|
+
@available_locales = nil
|
28
29
|
end
|
29
30
|
|
30
31
|
def locale_files
|
31
|
-
|
32
|
+
@locale_files ||= settings.locales.flat_map { |path|
|
32
33
|
Dir["#{path}/*.yml"]
|
33
|
-
|
34
|
+
}
|
34
35
|
end
|
35
36
|
|
36
37
|
def available_locales
|
37
|
-
|
38
|
+
@available_locales ||= locale_files.map { |path| File.basename(path, ".yml") }.uniq
|
38
39
|
end
|
39
40
|
|
40
41
|
def find_locale_files(lang)
|
@@ -63,32 +64,35 @@ module Sidekiq
|
|
63
64
|
end
|
64
65
|
|
65
66
|
def poll_path
|
66
|
-
if current_path !=
|
67
|
-
root_path + current_path
|
67
|
+
if current_path != "" && params["poll"]
|
68
|
+
path = root_path + current_path
|
69
|
+
query_string = to_query_string(params.slice(*params.keys - %w[page poll]))
|
70
|
+
path += "?#{query_string}" unless query_string.empty?
|
71
|
+
path
|
68
72
|
else
|
69
73
|
""
|
70
74
|
end
|
71
75
|
end
|
72
76
|
|
73
77
|
def text_direction
|
74
|
-
get_locale[
|
78
|
+
get_locale["TextDirection"] || "ltr"
|
75
79
|
end
|
76
80
|
|
77
81
|
def rtl?
|
78
|
-
text_direction ==
|
82
|
+
text_direction == "rtl"
|
79
83
|
end
|
80
84
|
|
81
85
|
# See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
82
86
|
def user_preferred_languages
|
83
|
-
languages = env[
|
84
|
-
languages.to_s.downcase.gsub(/\s+/,
|
85
|
-
locale, quality = language.split(
|
86
|
-
locale
|
87
|
+
languages = env["HTTP_ACCEPT_LANGUAGE"]
|
88
|
+
languages.to_s.downcase.gsub(/\s+/, "").split(",").map { |language|
|
89
|
+
locale, quality = language.split(";q=", 2)
|
90
|
+
locale = nil if locale == "*" # Ignore wildcards
|
87
91
|
quality = quality ? quality.to_f : 1.0
|
88
92
|
[locale, quality]
|
89
|
-
|
93
|
+
}.sort { |(_, left), (_, right)|
|
90
94
|
right <=> left
|
91
|
-
|
95
|
+
}.map(&:first).compact
|
92
96
|
end
|
93
97
|
|
94
98
|
# Given an Accept-Language header like "fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,ru;q=0.2"
|
@@ -97,31 +101,38 @@ module Sidekiq
|
|
97
101
|
# Inspiration taken from https://github.com/iain/http_accept_language/blob/master/lib/http_accept_language/parser.rb
|
98
102
|
def locale
|
99
103
|
@locale ||= begin
|
100
|
-
matched_locale = user_preferred_languages.map
|
101
|
-
preferred_language = preferred.split(
|
104
|
+
matched_locale = user_preferred_languages.map { |preferred|
|
105
|
+
preferred_language = preferred.split("-", 2).first
|
102
106
|
|
103
|
-
lang_group = available_locales.select
|
104
|
-
preferred_language == available.split(
|
105
|
-
|
107
|
+
lang_group = available_locales.select { |available|
|
108
|
+
preferred_language == available.split("-", 2).first
|
109
|
+
}
|
106
110
|
|
107
111
|
lang_group.find { |lang| lang == preferred } || lang_group.min_by(&:length)
|
108
|
-
|
112
|
+
}.compact.first
|
109
113
|
|
110
|
-
matched_locale ||
|
114
|
+
matched_locale || "en"
|
111
115
|
end
|
112
116
|
end
|
113
117
|
|
118
|
+
# within is used by Sidekiq Pro
|
119
|
+
def display_tags(job, within = nil)
|
120
|
+
job.tags.map { |tag|
|
121
|
+
"<span class='jobtag label label-info'>#{::Rack::Utils.escape_html(tag)}</span>"
|
122
|
+
}.join(" ")
|
123
|
+
end
|
124
|
+
|
114
125
|
# mperham/sidekiq#3243
|
115
126
|
def unfiltered?
|
116
|
-
yield unless env[
|
127
|
+
yield unless env["PATH_INFO"].start_with?("/filter/")
|
117
128
|
end
|
118
129
|
|
119
130
|
def get_locale
|
120
131
|
strings(locale)
|
121
132
|
end
|
122
133
|
|
123
|
-
def t(msg, options={})
|
124
|
-
string = get_locale[msg] || strings(
|
134
|
+
def t(msg, options = {})
|
135
|
+
string = get_locale[msg] || strings("en")[msg] || msg
|
125
136
|
if options.empty?
|
126
137
|
string
|
127
138
|
else
|
@@ -129,6 +140,10 @@ module Sidekiq
|
|
129
140
|
end
|
130
141
|
end
|
131
142
|
|
143
|
+
def sort_direction_label
|
144
|
+
params[:direction] == "asc" ? "↑" : "↓"
|
145
|
+
end
|
146
|
+
|
132
147
|
def workers
|
133
148
|
@workers ||= Sidekiq::Workers.new
|
134
149
|
end
|
@@ -141,12 +156,6 @@ module Sidekiq
|
|
141
156
|
@stats ||= Sidekiq::Stats.new
|
142
157
|
end
|
143
158
|
|
144
|
-
def retries_with_score(score)
|
145
|
-
Sidekiq.redis do |conn|
|
146
|
-
conn.zrangebyscore('retry', score, score)
|
147
|
-
end.map { |msg| Sidekiq.load_json(msg) }
|
148
|
-
end
|
149
|
-
|
150
159
|
def redis_connection
|
151
160
|
Sidekiq.redis do |conn|
|
152
161
|
c = conn.connection
|
@@ -163,24 +172,24 @@ module Sidekiq
|
|
163
172
|
end
|
164
173
|
|
165
174
|
def root_path
|
166
|
-
"#{env[
|
175
|
+
"#{env["SCRIPT_NAME"]}/"
|
167
176
|
end
|
168
177
|
|
169
178
|
def current_path
|
170
|
-
@current_path ||= request.path_info.gsub(/^\//,
|
179
|
+
@current_path ||= request.path_info.gsub(/^\//, "")
|
171
180
|
end
|
172
181
|
|
173
182
|
def current_status
|
174
|
-
workers.size == 0 ?
|
183
|
+
workers.size == 0 ? "idle" : "active"
|
175
184
|
end
|
176
185
|
|
177
186
|
def relative_time(time)
|
178
187
|
stamp = time.getutc.iso8601
|
179
|
-
%
|
188
|
+
%(<time class="ltr" dir="ltr" title="#{stamp}" datetime="#{stamp}">#{time}</time>)
|
180
189
|
end
|
181
190
|
|
182
191
|
def job_params(job, score)
|
183
|
-
"#{score}-#{job[
|
192
|
+
"#{score}-#{job["jid"]}"
|
184
193
|
end
|
185
194
|
|
186
195
|
def parse_params(params)
|
@@ -188,7 +197,7 @@ module Sidekiq
|
|
188
197
|
[score.to_f, jid]
|
189
198
|
end
|
190
199
|
|
191
|
-
SAFE_QPARAMS = %w
|
200
|
+
SAFE_QPARAMS = %w[page poll direction]
|
192
201
|
|
193
202
|
# Merge options with current params, filter safe params, and stringify to query string
|
194
203
|
def qparams(options)
|
@@ -197,9 +206,13 @@ module Sidekiq
|
|
197
206
|
options[key.to_s] = options.delete(key)
|
198
207
|
end
|
199
208
|
|
200
|
-
params.merge(options)
|
209
|
+
to_query_string(params.merge(options))
|
210
|
+
end
|
211
|
+
|
212
|
+
def to_query_string(params)
|
213
|
+
params.map { |key, value|
|
201
214
|
SAFE_QPARAMS.include?(key) ? "#{key}=#{CGI.escape(value.to_s)}" : next
|
202
|
-
|
215
|
+
}.compact.join("&")
|
203
216
|
end
|
204
217
|
|
205
218
|
def truncate(text, truncate_after_chars = 2000)
|
@@ -207,9 +220,16 @@ module Sidekiq
|
|
207
220
|
end
|
208
221
|
|
209
222
|
def display_args(args, truncate_after_chars = 2000)
|
210
|
-
args
|
211
|
-
|
212
|
-
|
223
|
+
return "Invalid job payload, args is nil" if args.nil?
|
224
|
+
return "Invalid job payload, args must be an Array, not #{args.class.name}" unless args.is_a?(Array)
|
225
|
+
|
226
|
+
begin
|
227
|
+
args.map { |arg|
|
228
|
+
h(truncate(to_display(arg), truncate_after_chars))
|
229
|
+
}.join(", ")
|
230
|
+
rescue
|
231
|
+
"Illegal job arguments: #{h args.inspect}"
|
232
|
+
end
|
213
233
|
end
|
214
234
|
|
215
235
|
def csrf_tag
|
@@ -217,23 +237,21 @@ module Sidekiq
|
|
217
237
|
end
|
218
238
|
|
219
239
|
def to_display(arg)
|
240
|
+
arg.inspect
|
241
|
+
rescue
|
220
242
|
begin
|
221
|
-
arg.
|
222
|
-
rescue
|
223
|
-
|
224
|
-
arg.to_s
|
225
|
-
rescue => ex
|
226
|
-
"Cannot display argument: [#{ex.class.name}] #{ex.message}"
|
227
|
-
end
|
243
|
+
arg.to_s
|
244
|
+
rescue => ex
|
245
|
+
"Cannot display argument: [#{ex.class.name}] #{ex.message}"
|
228
246
|
end
|
229
247
|
end
|
230
248
|
|
231
|
-
RETRY_JOB_KEYS = Set.new(%w
|
249
|
+
RETRY_JOB_KEYS = Set.new(%w[
|
232
250
|
queue class args retry_count retried_at failed_at
|
233
251
|
jid error_message error_class backtrace
|
234
252
|
error_backtrace enqueued_at retry wrapped
|
235
|
-
created_at
|
236
|
-
)
|
253
|
+
created_at tags
|
254
|
+
])
|
237
255
|
|
238
256
|
def retry_extra_items(retry_job)
|
239
257
|
@retry_extra_items ||= {}.tap do |extra|
|
@@ -250,8 +268,8 @@ module Sidekiq
|
|
250
268
|
return number
|
251
269
|
end
|
252
270
|
|
253
|
-
options = {delimiter:
|
254
|
-
parts = number.to_s.to_str.split(
|
271
|
+
options = {delimiter: ",", separator: "."}
|
272
|
+
parts = number.to_s.to_str.split(".")
|
255
273
|
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
|
256
274
|
parts.join(options[:separator])
|
257
275
|
end
|
@@ -259,8 +277,8 @@ module Sidekiq
|
|
259
277
|
def h(text)
|
260
278
|
::Rack::Utils.escape_html(text)
|
261
279
|
rescue ArgumentError => e
|
262
|
-
raise unless e.message.eql?(
|
263
|
-
text.encode!(
|
280
|
+
raise unless e.message.eql?("invalid byte sequence in UTF-8")
|
281
|
+
text.encode!("UTF-16", "UTF-8", invalid: :replace, replace: "").encode!("UTF-8", "UTF-16")
|
264
282
|
retry
|
265
283
|
end
|
266
284
|
|
@@ -277,7 +295,7 @@ module Sidekiq
|
|
277
295
|
end
|
278
296
|
|
279
297
|
def environment_title_prefix
|
280
|
-
environment = Sidekiq.options[:environment] || ENV[
|
298
|
+
environment = Sidekiq.options[:environment] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
281
299
|
|
282
300
|
"[#{environment.upcase}] " unless environment == "production"
|
283
301
|
end
|
@@ -287,30 +305,30 @@ module Sidekiq
|
|
287
305
|
end
|
288
306
|
|
289
307
|
def server_utc_time
|
290
|
-
Time.now.utc.strftime(
|
308
|
+
Time.now.utc.strftime("%H:%M:%S UTC")
|
291
309
|
end
|
292
310
|
|
293
311
|
def redis_connection_and_namespace
|
294
312
|
@redis_connection_and_namespace ||= begin
|
295
|
-
namespace_suffix = namespace
|
313
|
+
namespace_suffix = namespace.nil? ? "" : "##{namespace}"
|
296
314
|
"#{redis_connection}#{namespace_suffix}"
|
297
315
|
end
|
298
316
|
end
|
299
317
|
|
300
318
|
def retry_or_delete_or_kill(job, params)
|
301
|
-
if params[
|
319
|
+
if params["retry"]
|
302
320
|
job.retry
|
303
|
-
elsif params[
|
321
|
+
elsif params["delete"]
|
304
322
|
job.delete
|
305
|
-
elsif params[
|
323
|
+
elsif params["kill"]
|
306
324
|
job.kill
|
307
325
|
end
|
308
326
|
end
|
309
327
|
|
310
328
|
def delete_or_add_queue(job, params)
|
311
|
-
if params[
|
329
|
+
if params["delete"]
|
312
330
|
job.delete
|
313
|
-
elsif params[
|
331
|
+
elsif params["add_to_queue"]
|
314
332
|
job.add_to_queue
|
315
333
|
end
|
316
334
|
end
|