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