sidekiq 5.2.8 → 6.1.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.

Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
  3. data/.github/workflows/ci.yml +41 -0
  4. data/.gitignore +0 -2
  5. data/.standard.yml +20 -0
  6. data/5.0-Upgrade.md +1 -1
  7. data/6.0-Upgrade.md +72 -0
  8. data/Changes.md +196 -0
  9. data/Ent-2.0-Upgrade.md +37 -0
  10. data/Ent-Changes.md +72 -1
  11. data/Gemfile +12 -11
  12. data/Gemfile.lock +193 -0
  13. data/Pro-5.0-Upgrade.md +25 -0
  14. data/Pro-Changes.md +56 -2
  15. data/README.md +18 -34
  16. data/Rakefile +5 -4
  17. data/bin/sidekiq +26 -2
  18. data/bin/sidekiqload +32 -24
  19. data/bin/sidekiqmon +8 -0
  20. data/lib/generators/sidekiq/templates/worker_test.rb.erb +1 -1
  21. data/lib/generators/sidekiq/worker_generator.rb +21 -13
  22. data/lib/sidekiq/api.rb +245 -219
  23. data/lib/sidekiq/cli.rb +144 -180
  24. data/lib/sidekiq/client.rb +68 -48
  25. data/lib/sidekiq/delay.rb +5 -6
  26. data/lib/sidekiq/exception_handler.rb +10 -12
  27. data/lib/sidekiq/extensions/action_mailer.rb +13 -22
  28. data/lib/sidekiq/extensions/active_record.rb +13 -10
  29. data/lib/sidekiq/extensions/class_methods.rb +14 -11
  30. data/lib/sidekiq/extensions/generic_proxy.rb +4 -4
  31. data/lib/sidekiq/fetch.rb +29 -30
  32. data/lib/sidekiq/job_logger.rb +45 -7
  33. data/lib/sidekiq/job_retry.rb +62 -61
  34. data/lib/sidekiq/launcher.rb +112 -54
  35. data/lib/sidekiq/logger.rb +166 -0
  36. data/lib/sidekiq/manager.rb +11 -13
  37. data/lib/sidekiq/middleware/chain.rb +15 -5
  38. data/lib/sidekiq/middleware/i18n.rb +5 -7
  39. data/lib/sidekiq/monitor.rb +133 -0
  40. data/lib/sidekiq/paginator.rb +18 -14
  41. data/lib/sidekiq/processor.rb +71 -70
  42. data/lib/sidekiq/rails.rb +29 -37
  43. data/lib/sidekiq/redis_connection.rb +50 -48
  44. data/lib/sidekiq/scheduled.rb +28 -29
  45. data/lib/sidekiq/sd_notify.rb +149 -0
  46. data/lib/sidekiq/systemd.rb +24 -0
  47. data/lib/sidekiq/testing/inline.rb +2 -1
  48. data/lib/sidekiq/testing.rb +35 -24
  49. data/lib/sidekiq/util.rb +17 -16
  50. data/lib/sidekiq/version.rb +2 -1
  51. data/lib/sidekiq/web/action.rb +14 -10
  52. data/lib/sidekiq/web/application.rb +74 -72
  53. data/lib/sidekiq/web/csrf_protection.rb +156 -0
  54. data/lib/sidekiq/web/helpers.rb +97 -77
  55. data/lib/sidekiq/web/router.rb +18 -17
  56. data/lib/sidekiq/web.rb +53 -53
  57. data/lib/sidekiq/worker.rb +126 -102
  58. data/lib/sidekiq.rb +69 -44
  59. data/sidekiq.gemspec +15 -16
  60. data/web/assets/javascripts/application.js +25 -27
  61. data/web/assets/javascripts/dashboard.js +4 -23
  62. data/web/assets/stylesheets/application-dark.css +149 -0
  63. data/web/assets/stylesheets/application.css +28 -6
  64. data/web/locales/de.yml +14 -2
  65. data/web/locales/en.yml +2 -0
  66. data/web/locales/fr.yml +3 -3
  67. data/web/locales/ja.yml +4 -1
  68. data/web/locales/lt.yml +83 -0
  69. data/web/locales/pl.yml +4 -4
  70. data/web/locales/ru.yml +4 -0
  71. data/web/locales/vi.yml +83 -0
  72. data/web/views/_job_info.erb +2 -1
  73. data/web/views/busy.erb +8 -3
  74. data/web/views/dead.erb +2 -2
  75. data/web/views/layout.erb +1 -0
  76. data/web/views/morgue.erb +5 -2
  77. data/web/views/queue.erb +10 -1
  78. data/web/views/queues.erb +9 -1
  79. data/web/views/retries.erb +5 -2
  80. data/web/views/retry.erb +2 -2
  81. data/web/views/scheduled.erb +5 -2
  82. metadata +31 -49
  83. data/.circleci/config.yml +0 -61
  84. data/.github/issue_template.md +0 -11
  85. data/.travis.yml +0 -11
  86. data/bin/sidekiqctl +0 -20
  87. data/lib/sidekiq/core_ext.rb +0 -1
  88. data/lib/sidekiq/ctl.rb +0 -221
  89. data/lib/sidekiq/logging.rb +0 -122
  90. data/lib/sidekiq/middleware/server/active_record.rb +0 -23
@@ -1,15 +1,16 @@
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
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
- @@strings = nil
26
- @@locale_files = nil
27
- @@available_locales = nil
26
+ @strings = nil
27
+ @locale_files = nil
28
+ @available_locales = nil
28
29
  end
29
30
 
30
31
  def locale_files
31
- @@locale_files ||= settings.locales.flat_map do |path|
32
+ @locale_files ||= settings.locales.flat_map { |path|
32
33
  Dir["#{path}/*.yml"]
33
- end
34
+ }
34
35
  end
35
36
 
36
37
  def available_locales
37
- @@available_locales ||= locale_files.map { |path| File.basename(path, '.yml') }.uniq
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 != '' && params['poll']
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['TextDirection'] || 'ltr'
78
+ get_locale["TextDirection"] || "ltr"
75
79
  end
76
80
 
77
81
  def rtl?
78
- text_direction == 'rtl'
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['HTTP_ACCEPT_LANGUAGE']
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
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
- end.sort do |(_, left), (_, right)|
93
+ }.sort { |(_, left), (_, right)|
90
94
  right <=> left
91
- end.map(&:first).compact
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 do |preferred|
101
- preferred_language = preferred.split('-', 2).first
104
+ matched_locale = user_preferred_languages.map { |preferred|
105
+ preferred_language = preferred.split("-", 2).first
102
106
 
103
- lang_group = available_locales.select do |available|
104
- preferred_language == available.split('-', 2).first
105
- end
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
- end.compact.first
112
+ }.compact.first
109
113
 
110
- matched_locale || 'en'
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['PATH_INFO'].start_with?("/filter/")
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('en')[msg] || msg
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" ? "&uarr;" : "&darr;"
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['SCRIPT_NAME']}/"
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 ? 'idle' : 'active'
183
+ workers.size == 0 ? "idle" : "active"
175
184
  end
176
185
 
177
186
  def relative_time(time)
178
187
  stamp = time.getutc.iso8601
179
- %{<time class="ltr" dir="ltr" title="#{stamp}" datetime="#{stamp}">#{time}</time>}
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['jid']}"
192
+ "#{score}-#{job["jid"]}"
184
193
  end
185
194
 
186
195
  def parse_params(params)
@@ -188,18 +197,19 @@ module Sidekiq
188
197
  [score.to_f, jid]
189
198
  end
190
199
 
191
- SAFE_QPARAMS = %w(page poll)
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)
195
- # stringify
196
- options.keys.each do |key|
197
- options[key.to_s] = options.delete(key)
198
- end
204
+ stringified_options = options.transform_keys(&:to_s)
199
205
 
200
- params.merge(options).map do |key, value|
206
+ to_query_string(params.merge(stringified_options))
207
+ end
208
+
209
+ def to_query_string(params)
210
+ params.map { |key, value|
201
211
  SAFE_QPARAMS.include?(key) ? "#{key}=#{CGI.escape(value.to_s)}" : next
202
- end.compact.join("&")
212
+ }.compact.join("&")
203
213
  end
204
214
 
205
215
  def truncate(text, truncate_after_chars = 2000)
@@ -207,40 +217,38 @@ module Sidekiq
207
217
  end
208
218
 
209
219
  def display_args(args, truncate_after_chars = 2000)
210
- return "Invalid job payload, args is nil" if args == nil
211
- return "Invalid job payload, args must be an Array, not #{args.class.name}" if !args.is_a?(Array)
220
+ return "Invalid job payload, args is nil" if args.nil?
221
+ return "Invalid job payload, args must be an Array, not #{args.class.name}" unless args.is_a?(Array)
212
222
 
213
223
  begin
214
- args.map do |arg|
224
+ args.map { |arg|
215
225
  h(truncate(to_display(arg), truncate_after_chars))
216
- end.join(", ")
226
+ }.join(", ")
217
227
  rescue
218
228
  "Illegal job arguments: #{h args.inspect}"
219
229
  end
220
230
  end
221
231
 
222
232
  def csrf_tag
223
- "<input type='hidden' name='authenticity_token' value='#{session[:csrf]}'/>"
233
+ "<input type='hidden' name='authenticity_token' value='#{env[:csrf_token]}'/>"
224
234
  end
225
235
 
226
236
  def to_display(arg)
237
+ arg.inspect
238
+ rescue
227
239
  begin
228
- arg.inspect
229
- rescue
230
- begin
231
- arg.to_s
232
- rescue => ex
233
- "Cannot display argument: [#{ex.class.name}] #{ex.message}"
234
- end
240
+ arg.to_s
241
+ rescue => ex
242
+ "Cannot display argument: [#{ex.class.name}] #{ex.message}"
235
243
  end
236
244
  end
237
245
 
238
- RETRY_JOB_KEYS = Set.new(%w(
246
+ RETRY_JOB_KEYS = Set.new(%w[
239
247
  queue class args retry_count retried_at failed_at
240
248
  jid error_message error_class backtrace
241
249
  error_backtrace enqueued_at retry wrapped
242
- created_at
243
- ))
250
+ created_at tags
251
+ ])
244
252
 
245
253
  def retry_extra_items(retry_job)
246
254
  @retry_extra_items ||= {}.tap do |extra|
@@ -250,15 +258,27 @@ module Sidekiq
250
258
  end
251
259
  end
252
260
 
261
+ def format_memory(rss_kb)
262
+ return "" if rss_kb.nil? || rss_kb == 0
263
+
264
+ if rss_kb < 100_000
265
+ "#{number_with_delimiter(rss_kb)} KB"
266
+ else
267
+ "#{number_with_delimiter((rss_kb / 1024.0).to_i)} MB"
268
+ end
269
+ end
270
+
253
271
  def number_with_delimiter(number)
272
+ return "" if number.nil?
273
+
254
274
  begin
255
275
  Float(number)
256
276
  rescue ArgumentError, TypeError
257
277
  return number
258
278
  end
259
279
 
260
- options = {delimiter: ',', separator: '.'}
261
- parts = number.to_s.to_str.split('.')
280
+ options = {delimiter: ",", separator: "."}
281
+ parts = number.to_s.to_str.split(".")
262
282
  parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
263
283
  parts.join(options[:separator])
264
284
  end
@@ -266,8 +286,8 @@ module Sidekiq
266
286
  def h(text)
267
287
  ::Rack::Utils.escape_html(text)
268
288
  rescue ArgumentError => e
269
- raise unless e.message.eql?('invalid byte sequence in UTF-8')
270
- text.encode!('UTF-16', 'UTF-8', invalid: :replace, replace: '').encode!('UTF-8', 'UTF-16')
289
+ raise unless e.message.eql?("invalid byte sequence in UTF-8")
290
+ text.encode!("UTF-16", "UTF-8", invalid: :replace, replace: "").encode!("UTF-8", "UTF-16")
271
291
  retry
272
292
  end
273
293
 
@@ -284,7 +304,7 @@ module Sidekiq
284
304
  end
285
305
 
286
306
  def environment_title_prefix
287
- environment = Sidekiq.options[:environment] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
307
+ environment = Sidekiq.options[:environment] || ENV["APP_ENV"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
288
308
 
289
309
  "[#{environment.upcase}] " unless environment == "production"
290
310
  end
@@ -294,30 +314,30 @@ module Sidekiq
294
314
  end
295
315
 
296
316
  def server_utc_time
297
- Time.now.utc.strftime('%H:%M:%S UTC')
317
+ Time.now.utc.strftime("%H:%M:%S UTC")
298
318
  end
299
319
 
300
320
  def redis_connection_and_namespace
301
321
  @redis_connection_and_namespace ||= begin
302
- namespace_suffix = namespace == nil ? '' : "##{namespace}"
322
+ namespace_suffix = namespace.nil? ? "" : "##{namespace}"
303
323
  "#{redis_connection}#{namespace_suffix}"
304
324
  end
305
325
  end
306
326
 
307
327
  def retry_or_delete_or_kill(job, params)
308
- if params['retry']
328
+ if params["retry"]
309
329
  job.retry
310
- elsif params['delete']
330
+ elsif params["delete"]
311
331
  job.delete
312
- elsif params['kill']
332
+ elsif params["kill"]
313
333
  job.kill
314
334
  end
315
335
  end
316
336
 
317
337
  def delete_or_add_queue(job, params)
318
- if params['delete']
338
+ if params["delete"]
319
339
  job.delete
320
- elsif params['add_to_queue']
340
+ elsif params["add_to_queue"]
321
341
  job.add_to_queue
322
342
  end
323
343
  end
@@ -1,18 +1,19 @@
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'
7
- DELETE = 'DELETE'
8
- POST = 'POST'
9
- PUT = 'PUT'
10
- PATCH = 'PATCH'
11
- HEAD = 'HEAD'
7
+ GET = "GET"
8
+ DELETE = "DELETE"
9
+ POST = "POST"
10
+ PUT = "PUT"
11
+ PATCH = "PATCH"
12
+ HEAD = "HEAD"
12
13
 
13
- ROUTE_PARAMS = 'rack.route_params'
14
- REQUEST_METHOD = 'REQUEST_METHOD'
15
- PATH_INFO = '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 ||= { GET => [], POST => [], PUT => [], PATCH => [], DELETE => [], HEAD => [] }
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
- if params = route.match(request_method, path_info)
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)
@@ -64,7 +66,7 @@ module Sidekiq
64
66
  class WebRoute
65
67
  attr_accessor :request_method, :pattern, :block, :name
66
68
 
67
- NAMED_SEGMENTS_PATTERN = /\/([^\/]*):([^\.:$\/]+)/
69
+ NAMED_SEGMENTS_PATTERN = /\/([^\/]*):([^.:$\/]+)/
68
70
 
69
71
  def initialize(request_method, pattern, block)
70
72
  @request_method = request_method
@@ -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,9 +93,8 @@ module Sidekiq
91
93
  when String
92
94
  {} if path == matcher
93
95
  else
94
- if path_match = path.match(matcher)
95
- Hash[path_match.names.map(&:to_sym).zip(path_match.captures)]
96
- end
96
+ path_match = path.match(matcher)
97
+ path_match&.named_captures&.transform_keys(&:to_sym)
97
98
  end
98
99
  end
99
100
  end
data/lib/sidekiq/web.rb CHANGED
@@ -1,20 +1,22 @@
1
1
  # frozen_string_literal: true
2
- require 'erb'
3
2
 
4
- require 'sidekiq'
5
- require 'sidekiq/api'
6
- require 'sidekiq/paginator'
7
- require 'sidekiq/web/helpers'
3
+ require "erb"
8
4
 
9
- require 'sidekiq/web/router'
10
- require 'sidekiq/web/action'
11
- require 'sidekiq/web/application'
5
+ require "sidekiq"
6
+ require "sidekiq/api"
7
+ require "sidekiq/paginator"
8
+ require "sidekiq/web/helpers"
12
9
 
13
- require 'rack/protection'
10
+ require "sidekiq/web/router"
11
+ require "sidekiq/web/action"
12
+ require "sidekiq/web/application"
13
+ require "sidekiq/web/csrf_protection"
14
14
 
15
- require 'rack/builder'
16
- require 'rack/file'
17
- require 'rack/session/cookie'
15
+ require "rack/content_length"
16
+
17
+ require "rack/builder"
18
+ require "rack/file"
19
+ require "rack/session/cookie"
18
20
 
19
21
  module Sidekiq
20
22
  class Web
@@ -25,12 +27,12 @@ module Sidekiq
25
27
  ASSETS = "#{ROOT}/assets"
26
28
 
27
29
  DEFAULT_TABS = {
28
- "Dashboard" => '',
29
- "Busy" => 'busy',
30
- "Queues" => 'queues',
31
- "Retries" => 'retries',
32
- "Scheduled" => 'scheduled',
33
- "Dead" => 'morgue',
30
+ "Dashboard" => "",
31
+ "Busy" => "busy",
32
+ "Queues" => "queues",
33
+ "Retries" => "retries",
34
+ "Scheduled" => "scheduled",
35
+ "Dead" => "morgue"
34
36
  }
35
37
 
36
38
  class << self
@@ -64,11 +66,11 @@ module Sidekiq
64
66
  end
65
67
 
66
68
  def enable(*opts)
67
- opts.each {|key| set(key, true) }
69
+ opts.each { |key| set(key, true) }
68
70
  end
69
71
 
70
72
  def disable(*opts)
71
- opts.each {|key| set(key, false) }
73
+ opts.each { |key| set(key, false) }
72
74
  end
73
75
 
74
76
  # Helper for the Sinatra syntax: Sidekiq::Web.set(:session_secret, Rails.application.secrets...)
@@ -81,10 +83,10 @@ module Sidekiq
81
83
  end
82
84
 
83
85
  def self.inherited(child)
84
- child.app_url = self.app_url
85
- child.session_secret = self.session_secret
86
- child.redis_pool = self.redis_pool
87
- child.sessions = self.sessions
86
+ child.app_url = app_url
87
+ child.session_secret = session_secret
88
+ child.redis_pool = redis_pool
89
+ child.sessions = sessions
88
90
  end
89
91
 
90
92
  def settings
@@ -113,11 +115,11 @@ module Sidekiq
113
115
  end
114
116
 
115
117
  def enable(*opts)
116
- opts.each {|key| set(key, true) }
118
+ opts.each { |key| set(key, true) }
117
119
  end
118
120
 
119
121
  def disable(*opts)
120
- opts.each {|key| set(key, false) }
122
+ opts.each { |key| set(key, false) }
121
123
  end
122
124
 
123
125
  def set(attribute, value)
@@ -145,32 +147,39 @@ module Sidekiq
145
147
  private
146
148
 
147
149
  def using?(middleware)
148
- middlewares.any? do |(m,_)|
149
- m.kind_of?(Array) && (m[0] == middleware || m[0].kind_of?(middleware))
150
+ middlewares.any? do |(m, _)|
151
+ m.is_a?(Array) && (m[0] == middleware || m[0].is_a?(middleware))
150
152
  end
151
153
  end
152
154
 
153
155
  def build_sessions
154
156
  middlewares = self.middlewares
155
157
 
156
- unless using?(::Rack::Protection) || ENV['RACK_ENV'] == 'test'
157
- middlewares.unshift [[::Rack::Protection, { use: :authenticity_token }], nil]
158
- end
159
-
160
158
  s = sessions
161
- return unless s
162
159
 
163
- unless using? ::Rack::Session::Cookie
164
- unless secret = Web.session_secret
165
- require 'securerandom'
160
+ # turn on CSRF protection if sessions are enabled and this is not the test env
161
+ if s && !using?(CsrfProtection) && ENV["RACK_ENV"] != "test"
162
+ middlewares.unshift [[CsrfProtection], nil]
163
+ end
164
+
165
+ if s && !using?(::Rack::Session::Cookie)
166
+ unless (secret = Web.session_secret)
167
+ require "securerandom"
166
168
  secret = SecureRandom.hex(64)
167
169
  end
168
170
 
169
- options = { secret: secret }
171
+ options = {secret: secret}
170
172
  options = options.merge(s.to_hash) if s.respond_to? :to_hash
171
173
 
172
174
  middlewares.unshift [[::Rack::Session::Cookie, options], nil]
173
175
  end
176
+
177
+ # Since Sidekiq::WebApplication no longer calculates its own
178
+ # Content-Length response header, we must ensure that the Rack middleware
179
+ # that does this is loaded
180
+ unless using? ::Rack::ContentLength
181
+ middlewares.unshift [[::Rack::ContentLength], nil]
182
+ end
174
183
  end
175
184
 
176
185
  def build
@@ -180,13 +189,13 @@ module Sidekiq
180
189
  klass = self.class
181
190
 
182
191
  ::Rack::Builder.new do
183
- %w(stylesheets javascripts images).each do |asset_dir|
192
+ %w[stylesheets javascripts images].each do |asset_dir|
184
193
  map "/#{asset_dir}" do
185
- run ::Rack::File.new("#{ASSETS}/#{asset_dir}", { 'Cache-Control' => 'public, max-age=86400' })
194
+ run ::Rack::File.new("#{ASSETS}/#{asset_dir}", {"Cache-Control" => "public, max-age=86400"})
186
195
  end
187
196
  end
188
197
 
189
- middlewares.each {|middleware, block| use(*middleware, &block) }
198
+ middlewares.each { |middleware, block| use(*middleware, &block) }
190
199
 
191
200
  run WebApplication.new(klass)
192
201
  end
@@ -196,18 +205,9 @@ module Sidekiq
196
205
  Sidekiq::WebApplication.helpers WebHelpers
197
206
  Sidekiq::WebApplication.helpers Sidekiq::Paginator
198
207
 
199
- Sidekiq::WebAction.class_eval "def _render\n#{ERB.new(File.read(Web::LAYOUT)).src}\nend"
200
- end
201
-
202
- if defined?(::ActionDispatch::Request::Session) &&
203
- !::ActionDispatch::Request::Session.method_defined?(:each)
204
- # mperham/sidekiq#2460
205
- # Rack apps can't reuse the Rails session store without
206
- # this monkeypatch, fixed in Rails 5.
207
- class ActionDispatch::Request::Session
208
- def each(&block)
209
- hash = self.to_hash
210
- hash.each(&block)
208
+ Sidekiq::WebAction.class_eval <<-RUBY, __FILE__, __LINE__ + 1
209
+ def _render
210
+ #{ERB.new(File.read(Web::LAYOUT)).src}
211
211
  end
212
- end
212
+ RUBY
213
213
  end