sidekiq 5.1.1 → 7.1.2

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.

Files changed (149) hide show
  1. checksums.yaml +5 -5
  2. data/Changes.md +627 -8
  3. data/LICENSE.txt +9 -0
  4. data/README.md +47 -50
  5. data/bin/sidekiq +22 -3
  6. data/bin/sidekiqload +213 -115
  7. data/bin/sidekiqmon +11 -0
  8. data/lib/generators/sidekiq/job_generator.rb +57 -0
  9. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
  10. data/lib/generators/sidekiq/templates/{worker_spec.rb.erb → job_spec.rb.erb} +1 -1
  11. data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
  12. data/lib/sidekiq/api.rb +566 -329
  13. data/lib/sidekiq/capsule.rb +127 -0
  14. data/lib/sidekiq/cli.rb +241 -256
  15. data/lib/sidekiq/client.rb +125 -102
  16. data/lib/sidekiq/component.rb +68 -0
  17. data/lib/sidekiq/config.rb +278 -0
  18. data/lib/sidekiq/deploy.rb +62 -0
  19. data/lib/sidekiq/embedded.rb +61 -0
  20. data/lib/sidekiq/fetch.rb +49 -42
  21. data/lib/sidekiq/job.rb +374 -0
  22. data/lib/sidekiq/job_logger.rb +36 -9
  23. data/lib/sidekiq/job_retry.rb +147 -98
  24. data/lib/sidekiq/job_util.rb +105 -0
  25. data/lib/sidekiq/launcher.rb +207 -103
  26. data/lib/sidekiq/logger.rb +131 -0
  27. data/lib/sidekiq/manager.rb +43 -47
  28. data/lib/sidekiq/metrics/query.rb +153 -0
  29. data/lib/sidekiq/metrics/shared.rb +95 -0
  30. data/lib/sidekiq/metrics/tracking.rb +136 -0
  31. data/lib/sidekiq/middleware/chain.rb +113 -56
  32. data/lib/sidekiq/middleware/current_attributes.rb +95 -0
  33. data/lib/sidekiq/middleware/i18n.rb +7 -7
  34. data/lib/sidekiq/middleware/modules.rb +21 -0
  35. data/lib/sidekiq/monitor.rb +146 -0
  36. data/lib/sidekiq/paginator.rb +28 -16
  37. data/lib/sidekiq/processor.rb +159 -107
  38. data/lib/sidekiq/rails.rb +54 -43
  39. data/lib/sidekiq/redis_client_adapter.rb +96 -0
  40. data/lib/sidekiq/redis_connection.rb +39 -81
  41. data/lib/sidekiq/ring_buffer.rb +29 -0
  42. data/lib/sidekiq/scheduled.rb +139 -48
  43. data/lib/sidekiq/sd_notify.rb +149 -0
  44. data/lib/sidekiq/systemd.rb +24 -0
  45. data/lib/sidekiq/testing/inline.rb +6 -5
  46. data/lib/sidekiq/testing.rb +70 -88
  47. data/lib/sidekiq/transaction_aware_client.rb +44 -0
  48. data/lib/sidekiq/version.rb +3 -1
  49. data/lib/sidekiq/web/action.rb +15 -11
  50. data/lib/sidekiq/web/application.rb +143 -77
  51. data/lib/sidekiq/web/csrf_protection.rb +180 -0
  52. data/lib/sidekiq/web/helpers.rb +144 -106
  53. data/lib/sidekiq/web/router.rb +23 -19
  54. data/lib/sidekiq/web.rb +60 -111
  55. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  56. data/lib/sidekiq.rb +94 -183
  57. data/sidekiq.gemspec +25 -23
  58. data/web/assets/images/apple-touch-icon.png +0 -0
  59. data/web/assets/javascripts/application.js +130 -61
  60. data/web/assets/javascripts/base-charts.js +106 -0
  61. data/web/assets/javascripts/chart.min.js +13 -0
  62. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  63. data/web/assets/javascripts/dashboard-charts.js +166 -0
  64. data/web/assets/javascripts/dashboard.js +36 -282
  65. data/web/assets/javascripts/metrics.js +264 -0
  66. data/web/assets/stylesheets/application-dark.css +147 -0
  67. data/web/assets/stylesheets/application-rtl.css +2 -95
  68. data/web/assets/stylesheets/application.css +134 -521
  69. data/web/assets/stylesheets/bootstrap.css +2 -2
  70. data/web/locales/ar.yml +71 -64
  71. data/web/locales/cs.yml +62 -62
  72. data/web/locales/da.yml +60 -53
  73. data/web/locales/de.yml +65 -53
  74. data/web/locales/el.yml +43 -24
  75. data/web/locales/en.yml +84 -65
  76. data/web/locales/es.yml +70 -54
  77. data/web/locales/fa.yml +65 -65
  78. data/web/locales/fr.yml +83 -62
  79. data/web/locales/gd.yml +99 -0
  80. data/web/locales/he.yml +65 -64
  81. data/web/locales/hi.yml +59 -59
  82. data/web/locales/it.yml +53 -53
  83. data/web/locales/ja.yml +75 -64
  84. data/web/locales/ko.yml +52 -52
  85. data/web/locales/lt.yml +83 -0
  86. data/web/locales/nb.yml +61 -61
  87. data/web/locales/nl.yml +52 -52
  88. data/web/locales/pl.yml +45 -45
  89. data/web/locales/pt-br.yml +63 -55
  90. data/web/locales/pt.yml +51 -51
  91. data/web/locales/ru.yml +68 -63
  92. data/web/locales/sv.yml +53 -53
  93. data/web/locales/ta.yml +60 -60
  94. data/web/locales/uk.yml +62 -61
  95. data/web/locales/ur.yml +64 -64
  96. data/web/locales/vi.yml +83 -0
  97. data/web/locales/zh-cn.yml +43 -16
  98. data/web/locales/zh-tw.yml +42 -8
  99. data/web/views/_footer.erb +8 -2
  100. data/web/views/_job_info.erb +21 -4
  101. data/web/views/_metrics_period_select.erb +12 -0
  102. data/web/views/_nav.erb +4 -18
  103. data/web/views/_paging.erb +2 -0
  104. data/web/views/_poll_link.erb +3 -6
  105. data/web/views/_summary.erb +7 -7
  106. data/web/views/busy.erb +75 -25
  107. data/web/views/dashboard.erb +58 -18
  108. data/web/views/dead.erb +3 -3
  109. data/web/views/layout.erb +4 -2
  110. data/web/views/metrics.erb +82 -0
  111. data/web/views/metrics_for_job.erb +68 -0
  112. data/web/views/morgue.erb +14 -15
  113. data/web/views/queue.erb +33 -23
  114. data/web/views/queues.erb +14 -4
  115. data/web/views/retries.erb +19 -16
  116. data/web/views/retry.erb +3 -3
  117. data/web/views/scheduled.erb +17 -15
  118. metadata +71 -140
  119. data/.github/contributing.md +0 -32
  120. data/.github/issue_template.md +0 -11
  121. data/.gitignore +0 -13
  122. data/.travis.yml +0 -14
  123. data/3.0-Upgrade.md +0 -70
  124. data/4.0-Upgrade.md +0 -53
  125. data/5.0-Upgrade.md +0 -56
  126. data/COMM-LICENSE +0 -95
  127. data/Ent-Changes.md +0 -210
  128. data/Gemfile +0 -8
  129. data/LICENSE +0 -9
  130. data/Pro-2.0-Upgrade.md +0 -138
  131. data/Pro-3.0-Upgrade.md +0 -44
  132. data/Pro-4.0-Upgrade.md +0 -35
  133. data/Pro-Changes.md +0 -716
  134. data/Rakefile +0 -8
  135. data/bin/sidekiqctl +0 -99
  136. data/code_of_conduct.md +0 -50
  137. data/lib/generators/sidekiq/worker_generator.rb +0 -49
  138. data/lib/sidekiq/core_ext.rb +0 -1
  139. data/lib/sidekiq/delay.rb +0 -41
  140. data/lib/sidekiq/exception_handler.rb +0 -29
  141. data/lib/sidekiq/extensions/action_mailer.rb +0 -57
  142. data/lib/sidekiq/extensions/active_record.rb +0 -40
  143. data/lib/sidekiq/extensions/class_methods.rb +0 -40
  144. data/lib/sidekiq/extensions/generic_proxy.rb +0 -31
  145. data/lib/sidekiq/logging.rb +0 -122
  146. data/lib/sidekiq/middleware/server/active_record.rb +0 -22
  147. data/lib/sidekiq/middleware/server/active_record_cache.rb +0 -11
  148. data/lib/sidekiq/util.rb +0 -66
  149. data/lib/sidekiq/worker.rb +0 -204
@@ -1,40 +1,48 @@
1
1
  # frozen_string_literal: true
2
- require 'uri'
3
- require 'set'
4
- require 'yaml'
5
- require 'cgi'
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
- @@strings ||= {}
12
- @@strings[lang] ||= begin
13
- # Allow sidekiq-web extensions to add locale paths
14
- # so extensions can be localized
15
- settings.locales.each_with_object({}) do |path, global|
16
- find_locale_files(lang).each do |file|
17
- strs = YAML.load(File.open(file))
18
- global.merge!(strs[lang])
19
- end
12
+ @strings ||= {}
13
+
14
+ # Allow sidekiq-web extensions to add locale paths
15
+ # so extensions can be localized
16
+ @strings[lang] ||= settings.locales.each_with_object({}) do |path, global|
17
+ find_locale_files(lang).each do |file|
18
+ strs = YAML.safe_load(File.read(file))
19
+ global.merge!(strs[lang])
20
20
  end
21
21
  end
22
22
  end
23
23
 
24
+ def singularize(str, count)
25
+ if count == 1 && str.respond_to?(:singularize) # rails
26
+ str.singularize
27
+ else
28
+ str
29
+ end
30
+ end
31
+
24
32
  def clear_caches
25
- @@strings = nil
26
- @@locale_files = nil
27
- @@available_locales = nil
33
+ @strings = nil
34
+ @locale_files = nil
35
+ @available_locales = nil
28
36
  end
29
37
 
30
38
  def locale_files
31
- @@locale_files ||= settings.locales.flat_map do |path|
39
+ @locale_files ||= settings.locales.flat_map { |path|
32
40
  Dir["#{path}/*.yml"]
33
- end
41
+ }
34
42
  end
35
43
 
36
44
  def available_locales
37
- @@available_locales ||= locale_files.map { |path| File.basename(path, '.yml') }.uniq
45
+ @available_locales ||= locale_files.map { |path| File.basename(path, ".yml") }.uniq
38
46
  end
39
47
 
40
48
  def find_locale_files(lang)
@@ -62,33 +70,25 @@ module Sidekiq
62
70
  @head_html.join if defined?(@head_html)
63
71
  end
64
72
 
65
- def poll_path
66
- if current_path != '' && params['poll']
67
- root_path + current_path
68
- else
69
- ""
70
- end
71
- end
72
-
73
73
  def text_direction
74
- get_locale['TextDirection'] || 'ltr'
74
+ get_locale["TextDirection"] || "ltr"
75
75
  end
76
76
 
77
77
  def rtl?
78
- text_direction == 'rtl'
78
+ text_direction == "rtl"
79
79
  end
80
80
 
81
81
  # See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
82
82
  def user_preferred_languages
83
- languages = env['HTTP_ACCEPT_LANGUAGE'.freeze]
84
- languages.to_s.downcase.gsub(/\s+/, '').split(',').map do |language|
85
- locale, quality = language.split(';q=', 2)
86
- locale = nil if locale == '*' # Ignore wildcards
83
+ languages = env["HTTP_ACCEPT_LANGUAGE"]
84
+ languages.to_s.downcase.gsub(/\s+/, "").split(",").map { |language|
85
+ locale, quality = language.split(";q=", 2)
86
+ locale = nil if locale == "*" # Ignore wildcards
87
87
  quality = quality ? quality.to_f : 1.0
88
88
  [locale, quality]
89
- end.sort do |(_, left), (_, right)|
89
+ }.sort { |(_, left), (_, right)|
90
90
  right <=> left
91
- end.map(&:first).compact
91
+ }.map(&:first).compact
92
92
  end
93
93
 
94
94
  # 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 +97,38 @@ module Sidekiq
97
97
  # Inspiration taken from https://github.com/iain/http_accept_language/blob/master/lib/http_accept_language/parser.rb
98
98
  def locale
99
99
  @locale ||= begin
100
- matched_locale = user_preferred_languages.map do |preferred|
101
- preferred_language = preferred.split('-', 2).first
100
+ matched_locale = user_preferred_languages.map { |preferred|
101
+ preferred_language = preferred.split("-", 2).first
102
102
 
103
- lang_group = available_locales.select do |available|
104
- preferred_language == available.split('-', 2).first
105
- end
103
+ lang_group = available_locales.select { |available|
104
+ preferred_language == available.split("-", 2).first
105
+ }
106
106
 
107
107
  lang_group.find { |lang| lang == preferred } || lang_group.min_by(&:length)
108
- end.compact.first
108
+ }.compact.first
109
109
 
110
- matched_locale || 'en'
110
+ matched_locale || "en"
111
111
  end
112
112
  end
113
113
 
114
- # mperham/sidekiq#3243
114
+ # within is used by Sidekiq Pro
115
+ def display_tags(job, within = nil)
116
+ job.tags.map { |tag|
117
+ "<span class='label label-info jobtag'>#{::Rack::Utils.escape_html(tag)}</span>"
118
+ }.join(" ")
119
+ end
120
+
121
+ # sidekiq/sidekiq#3243
115
122
  def unfiltered?
116
- yield unless env['PATH_INFO'].start_with?("/filter/")
123
+ yield unless env["PATH_INFO"].start_with?("/filter/")
117
124
  end
118
125
 
119
126
  def get_locale
120
127
  strings(locale)
121
128
  end
122
129
 
123
- def t(msg, options={})
124
- string = get_locale[msg] || msg
130
+ def t(msg, options = {})
131
+ string = get_locale[msg] || strings("en")[msg] || msg
125
132
  if options.empty?
126
133
  string
127
134
  else
@@ -129,111 +136,131 @@ module Sidekiq
129
136
  end
130
137
  end
131
138
 
132
- def workers
133
- @workers ||= Sidekiq::Workers.new
139
+ def sort_direction_label
140
+ (params[:direction] == "asc") ? "&uarr;" : "&darr;"
141
+ end
142
+
143
+ def workset
144
+ @work ||= Sidekiq::WorkSet.new
134
145
  end
135
146
 
136
147
  def processes
137
148
  @processes ||= Sidekiq::ProcessSet.new
138
149
  end
139
150
 
140
- def stats
141
- @stats ||= Sidekiq::Stats.new
151
+ # Sorts processes by hostname following the natural sort order
152
+ def sorted_processes
153
+ @sorted_processes ||= begin
154
+ return processes unless processes.all? { |p| p["hostname"] }
155
+
156
+ processes.to_a.sort_by do |process|
157
+ # Kudos to `shurikk` on StackOverflow
158
+ # https://stackoverflow.com/a/15170063/575547
159
+ process["hostname"].split(/(\d+)/).map { |a| /\d+/.match?(a) ? a.to_i : a }
160
+ end
161
+ end
142
162
  end
143
163
 
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) }
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("; ")
148
170
  end
149
171
 
150
- def redis_connection
151
- Sidekiq.redis do |conn|
152
- c = conn.connection
153
- "redis://#{c[:location]}/#{c[:db]}"
154
- end
172
+ def stats
173
+ @stats ||= Sidekiq::Stats.new
155
174
  end
156
175
 
157
- def namespace
158
- @@ns ||= Sidekiq.redis { |conn| conn.respond_to?(:namespace) ? conn.namespace : nil }
176
+ def redis_url
177
+ Sidekiq.redis do |conn|
178
+ conn.config.server_url
179
+ end
159
180
  end
160
181
 
161
182
  def redis_info
162
- Sidekiq.redis_info
183
+ Sidekiq.default_configuration.redis_info
163
184
  end
164
185
 
165
186
  def root_path
166
- "#{env['SCRIPT_NAME']}/"
187
+ "#{env["SCRIPT_NAME"]}/"
167
188
  end
168
189
 
169
190
  def current_path
170
- @current_path ||= request.path_info.gsub(/^\//,'')
191
+ @current_path ||= request.path_info.gsub(/^\//, "")
171
192
  end
172
193
 
173
194
  def current_status
174
- workers.size == 0 ? 'idle' : 'active'
195
+ (workset.size == 0) ? "idle" : "active"
175
196
  end
176
197
 
177
198
  def relative_time(time)
178
199
  stamp = time.getutc.iso8601
179
- %{<time class="ltr" dir="ltr" title="#{stamp}" datetime="#{stamp}">#{time}</time>}
200
+ %(<time class="ltr" dir="ltr" title="#{stamp}" datetime="#{stamp}">#{time}</time>)
180
201
  end
181
202
 
182
203
  def job_params(job, score)
183
- "#{score}-#{job['jid']}"
204
+ "#{score}-#{job["jid"]}"
184
205
  end
185
206
 
186
207
  def parse_params(params)
187
- score, jid = params.split("-")
208
+ score, jid = params.split("-", 2)
188
209
  [score.to_f, jid]
189
210
  end
190
211
 
191
- SAFE_QPARAMS = %w(page poll)
212
+ SAFE_QPARAMS = %w[page direction]
192
213
 
193
214
  # Merge options with current params, filter safe params, and stringify to query string
194
215
  def qparams(options)
195
- # stringify
196
- options.keys.each do |key|
197
- options[key.to_s] = options.delete(key)
198
- end
216
+ stringified_options = options.transform_keys(&:to_s)
199
217
 
200
- params.merge(options).map do |key, value|
218
+ to_query_string(params.merge(stringified_options))
219
+ end
220
+
221
+ def to_query_string(params)
222
+ params.map { |key, value|
201
223
  SAFE_QPARAMS.include?(key) ? "#{key}=#{CGI.escape(value.to_s)}" : next
202
- end.compact.join("&")
224
+ }.compact.join("&")
203
225
  end
204
226
 
205
227
  def truncate(text, truncate_after_chars = 2000)
206
- 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
207
229
  end
208
230
 
209
231
  def display_args(args, truncate_after_chars = 2000)
210
- args.map do |arg|
211
- h(truncate(to_display(arg), truncate_after_chars))
212
- end.join(", ")
232
+ return "Invalid job payload, args is nil" if args.nil?
233
+ return "Invalid job payload, args must be an Array, not #{args.class.name}" unless args.is_a?(Array)
234
+
235
+ begin
236
+ args.map { |arg|
237
+ h(truncate(to_display(arg), truncate_after_chars))
238
+ }.join(", ")
239
+ rescue
240
+ "Illegal job arguments: #{h args.inspect}"
241
+ end
213
242
  end
214
243
 
215
244
  def csrf_tag
216
- "<input type='hidden' name='authenticity_token' value='#{session[:csrf]}'/>"
245
+ "<input type='hidden' name='authenticity_token' value='#{env[:csrf_token]}'/>"
217
246
  end
218
247
 
219
248
  def to_display(arg)
249
+ arg.inspect
250
+ rescue
220
251
  begin
221
- arg.inspect
222
- rescue
223
- begin
224
- arg.to_s
225
- rescue => ex
226
- "Cannot display argument: [#{ex.class.name}] #{ex.message}"
227
- end
252
+ arg.to_s
253
+ rescue => ex
254
+ "Cannot display argument: [#{ex.class.name}] #{ex.message}"
228
255
  end
229
256
  end
230
257
 
231
- RETRY_JOB_KEYS = Set.new(%w(
258
+ RETRY_JOB_KEYS = Set.new(%w[
232
259
  queue class args retry_count retried_at failed_at
233
260
  jid error_message error_class backtrace
234
261
  error_backtrace enqueued_at retry wrapped
235
- created_at
236
- ))
262
+ created_at tags display_class
263
+ ])
237
264
 
238
265
  def retry_extra_items(retry_job)
239
266
  @retry_extra_items ||= {}.tap do |extra|
@@ -243,15 +270,29 @@ module Sidekiq
243
270
  end
244
271
  end
245
272
 
273
+ def format_memory(rss_kb)
274
+ return "0" if rss_kb.nil? || rss_kb == 0
275
+
276
+ if rss_kb < 100_000
277
+ "#{number_with_delimiter(rss_kb)} KB"
278
+ elsif rss_kb < 10_000_000
279
+ "#{number_with_delimiter((rss_kb / 1024.0).to_i)} MB"
280
+ else
281
+ "#{number_with_delimiter((rss_kb / (1024.0 * 1024.0)).round(1))} GB"
282
+ end
283
+ end
284
+
246
285
  def number_with_delimiter(number)
286
+ return "" if number.nil?
287
+
247
288
  begin
248
289
  Float(number)
249
290
  rescue ArgumentError, TypeError
250
291
  return number
251
292
  end
252
293
 
253
- options = {delimiter: ',', separator: '.'}
254
- parts = number.to_s.to_str.split('.')
294
+ options = {delimiter: ",", separator: "."}
295
+ parts = number.to_s.to_str.split(".")
255
296
  parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
256
297
  parts.join(options[:separator])
257
298
  end
@@ -259,8 +300,8 @@ module Sidekiq
259
300
  def h(text)
260
301
  ::Rack::Utils.escape_html(text)
261
302
  rescue ArgumentError => e
262
- raise unless e.message.eql?('invalid byte sequence in UTF-8')
263
- text.encode!('UTF-16', 'UTF-8', invalid: :replace, replace: '').encode!('UTF-8', 'UTF-16')
303
+ raise unless e.message.eql?("invalid byte sequence in UTF-8")
304
+ text.encode!("UTF-16", "UTF-8", invalid: :replace, replace: "").encode!("UTF-8", "UTF-16")
264
305
  retry
265
306
  end
266
307
 
@@ -277,7 +318,7 @@ module Sidekiq
277
318
  end
278
319
 
279
320
  def environment_title_prefix
280
- environment = Sidekiq.options[:environment] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
321
+ environment = Sidekiq.default_configuration[:environment] || ENV["APP_ENV"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
281
322
 
282
323
  "[#{environment.upcase}] " unless environment == "production"
283
324
  end
@@ -287,30 +328,27 @@ module Sidekiq
287
328
  end
288
329
 
289
330
  def server_utc_time
290
- Time.now.utc.strftime('%H:%M:%S UTC')
331
+ Time.now.utc.strftime("%H:%M:%S UTC")
291
332
  end
292
333
 
293
- def redis_connection_and_namespace
294
- @redis_connection_and_namespace ||= begin
295
- namespace_suffix = namespace == nil ? '' : "##{namespace}"
296
- "#{redis_connection}#{namespace_suffix}"
297
- end
334
+ def pollable?
335
+ !(current_path == "" || current_path.start_with?("metrics"))
298
336
  end
299
337
 
300
338
  def retry_or_delete_or_kill(job, params)
301
- if params['retry']
339
+ if params["retry"]
302
340
  job.retry
303
- elsif params['delete']
341
+ elsif params["delete"]
304
342
  job.delete
305
- elsif params['kill']
343
+ elsif params["kill"]
306
344
  job.kill
307
345
  end
308
346
  end
309
347
 
310
348
  def delete_or_add_queue(job, params)
311
- if params['delete']
349
+ if params["delete"]
312
350
  job.delete
313
- elsif params['add_to_queue']
351
+ elsif params["add_to_queue"]
314
352
  job.add_to_queue
315
353
  end
316
354
  end
@@ -1,18 +1,23 @@
1
1
  # frozen_string_literal: true
2
- require 'rack'
2
+
3
+ require "rack"
3
4
 
4
5
  module Sidekiq
5
6
  module WebRouter
6
- GET = 'GET'.freeze
7
- DELETE = 'DELETE'.freeze
8
- POST = 'POST'.freeze
9
- PUT = 'PUT'.freeze
10
- PATCH = 'PATCH'.freeze
11
- HEAD = 'HEAD'.freeze
12
-
13
- ROUTE_PARAMS = 'rack.route_params'.freeze
14
- REQUEST_METHOD = 'REQUEST_METHOD'.freeze
15
- PATH_INFO = 'PATH_INFO'.freeze
7
+ GET = "GET"
8
+ DELETE = "DELETE"
9
+ POST = "POST"
10
+ PUT = "PUT"
11
+ PATCH = "PATCH"
12
+ HEAD = "HEAD"
13
+
14
+ ROUTE_PARAMS = "rack.route_params"
15
+ REQUEST_METHOD = "REQUEST_METHOD"
16
+ PATH_INFO = "PATH_INFO"
17
+
18
+ def head(path, &block)
19
+ route(HEAD, path, &block)
20
+ end
16
21
 
17
22
  def get(path, &block)
18
23
  route(GET, path, &block)
@@ -35,10 +40,9 @@ module Sidekiq
35
40
  end
36
41
 
37
42
  def route(method, path, &block)
38
- @routes ||= { GET => [], POST => [], PUT => [], PATCH => [], DELETE => [], HEAD => [] }
43
+ @routes ||= {GET => [], POST => [], PUT => [], PATCH => [], DELETE => [], HEAD => []}
39
44
 
40
45
  @routes[method] << WebRoute.new(method, path, block)
41
- @routes[HEAD] << WebRoute.new(method, path, block) if method == GET
42
46
  end
43
47
 
44
48
  def match(env)
@@ -50,7 +54,8 @@ module Sidekiq
50
54
  path_info = "/" if path_info == ""
51
55
 
52
56
  @routes[request_method].each do |route|
53
- if params = route.match(request_method, path_info)
57
+ params = route.match(request_method, path_info)
58
+ if params
54
59
  env[ROUTE_PARAMS] = params
55
60
 
56
61
  return WebAction.new(env, route.block)
@@ -64,7 +69,7 @@ module Sidekiq
64
69
  class WebRoute
65
70
  attr_accessor :request_method, :pattern, :block, :name
66
71
 
67
- NAMED_SEGMENTS_PATTERN = /\/([^\/]*):([^\.:$\/]+)/.freeze
72
+ NAMED_SEGMENTS_PATTERN = /\/([^\/]*):([^.:$\/]+)/
68
73
 
69
74
  def initialize(request_method, pattern, block)
70
75
  @request_method = request_method
@@ -77,7 +82,7 @@ module Sidekiq
77
82
  end
78
83
 
79
84
  def compile
80
- if pattern.match(NAMED_SEGMENTS_PATTERN)
85
+ if pattern.match?(NAMED_SEGMENTS_PATTERN)
81
86
  p = pattern.gsub(NAMED_SEGMENTS_PATTERN, '/\1(?<\2>[^$/]+)')
82
87
 
83
88
  Regexp.new("\\A#{p}\\Z")
@@ -91,9 +96,8 @@ module Sidekiq
91
96
  when String
92
97
  {} if path == matcher
93
98
  else
94
- if path_match = path.match(matcher)
95
- Hash[path_match.names.map(&:to_sym).zip(path_match.captures)]
96
- end
99
+ path_match = path.match(matcher)
100
+ path_match&.named_captures&.transform_keys(&:to_sym)
97
101
  end
98
102
  end
99
103
  end