sidekiq 5.2.1 → 6.4.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.

Files changed (106) hide show
  1. checksums.yaml +5 -5
  2. data/Changes.md +368 -1
  3. data/LICENSE +3 -3
  4. data/README.md +21 -37
  5. data/bin/sidekiq +26 -2
  6. data/bin/sidekiqload +33 -25
  7. data/bin/sidekiqmon +8 -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 +316 -246
  13. data/lib/sidekiq/cli.rb +195 -221
  14. data/lib/sidekiq/client.rb +42 -60
  15. data/lib/sidekiq/delay.rb +7 -6
  16. data/lib/sidekiq/exception_handler.rb +10 -12
  17. data/lib/sidekiq/extensions/action_mailer.rb +15 -24
  18. data/lib/sidekiq/extensions/active_record.rb +15 -12
  19. data/lib/sidekiq/extensions/class_methods.rb +16 -13
  20. data/lib/sidekiq/extensions/generic_proxy.rb +8 -6
  21. data/lib/sidekiq/fetch.rb +39 -31
  22. data/lib/sidekiq/job.rb +13 -0
  23. data/lib/sidekiq/job_logger.rb +47 -9
  24. data/lib/sidekiq/job_retry.rb +88 -68
  25. data/lib/sidekiq/job_util.rb +65 -0
  26. data/lib/sidekiq/launcher.rb +151 -61
  27. data/lib/sidekiq/logger.rb +166 -0
  28. data/lib/sidekiq/manager.rb +18 -22
  29. data/lib/sidekiq/middleware/chain.rb +20 -8
  30. data/lib/sidekiq/middleware/current_attributes.rb +57 -0
  31. data/lib/sidekiq/middleware/i18n.rb +5 -7
  32. data/lib/sidekiq/monitor.rb +133 -0
  33. data/lib/sidekiq/paginator.rb +18 -14
  34. data/lib/sidekiq/processor.rb +116 -82
  35. data/lib/sidekiq/rails.rb +42 -38
  36. data/lib/sidekiq/redis_connection.rb +49 -30
  37. data/lib/sidekiq/scheduled.rb +62 -28
  38. data/lib/sidekiq/sd_notify.rb +149 -0
  39. data/lib/sidekiq/systemd.rb +24 -0
  40. data/lib/sidekiq/testing/inline.rb +2 -1
  41. data/lib/sidekiq/testing.rb +36 -27
  42. data/lib/sidekiq/util.rb +57 -15
  43. data/lib/sidekiq/version.rb +2 -1
  44. data/lib/sidekiq/web/action.rb +15 -11
  45. data/lib/sidekiq/web/application.rb +95 -76
  46. data/lib/sidekiq/web/csrf_protection.rb +180 -0
  47. data/lib/sidekiq/web/helpers.rb +115 -91
  48. data/lib/sidekiq/web/router.rb +23 -19
  49. data/lib/sidekiq/web.rb +61 -105
  50. data/lib/sidekiq/worker.rb +259 -99
  51. data/lib/sidekiq.rb +79 -45
  52. data/sidekiq.gemspec +23 -18
  53. data/web/assets/images/apple-touch-icon.png +0 -0
  54. data/web/assets/javascripts/application.js +83 -64
  55. data/web/assets/javascripts/dashboard.js +66 -75
  56. data/web/assets/stylesheets/application-dark.css +143 -0
  57. data/web/assets/stylesheets/application-rtl.css +0 -4
  58. data/web/assets/stylesheets/application.css +75 -231
  59. data/web/assets/stylesheets/bootstrap.css +1 -1
  60. data/web/locales/ar.yml +9 -2
  61. data/web/locales/de.yml +14 -2
  62. data/web/locales/en.yml +7 -1
  63. data/web/locales/es.yml +18 -2
  64. data/web/locales/fr.yml +10 -3
  65. data/web/locales/ja.yml +7 -1
  66. data/web/locales/lt.yml +83 -0
  67. data/web/locales/pl.yml +4 -4
  68. data/web/locales/ru.yml +4 -0
  69. data/web/locales/vi.yml +83 -0
  70. data/web/views/_footer.erb +1 -1
  71. data/web/views/_job_info.erb +3 -2
  72. data/web/views/_nav.erb +3 -17
  73. data/web/views/_poll_link.erb +2 -5
  74. data/web/views/_summary.erb +7 -7
  75. data/web/views/busy.erb +54 -20
  76. data/web/views/dashboard.erb +22 -14
  77. data/web/views/dead.erb +3 -3
  78. data/web/views/layout.erb +3 -1
  79. data/web/views/morgue.erb +9 -6
  80. data/web/views/queue.erb +20 -10
  81. data/web/views/queues.erb +11 -3
  82. data/web/views/retries.erb +14 -7
  83. data/web/views/retry.erb +3 -3
  84. data/web/views/scheduled.erb +5 -2
  85. metadata +39 -54
  86. data/.github/contributing.md +0 -32
  87. data/.github/issue_template.md +0 -11
  88. data/.gitignore +0 -13
  89. data/.travis.yml +0 -14
  90. data/3.0-Upgrade.md +0 -70
  91. data/4.0-Upgrade.md +0 -53
  92. data/5.0-Upgrade.md +0 -56
  93. data/COMM-LICENSE +0 -95
  94. data/Ent-Changes.md +0 -221
  95. data/Gemfile +0 -14
  96. data/Pro-2.0-Upgrade.md +0 -138
  97. data/Pro-3.0-Upgrade.md +0 -44
  98. data/Pro-4.0-Upgrade.md +0 -35
  99. data/Pro-Changes.md +0 -739
  100. data/Rakefile +0 -8
  101. data/bin/sidekiqctl +0 -99
  102. data/code_of_conduct.md +0 -50
  103. data/lib/generators/sidekiq/worker_generator.rb +0 -49
  104. data/lib/sidekiq/core_ext.rb +0 -1
  105. data/lib/sidekiq/logging.rb +0 -122
  106. data/lib/sidekiq/middleware/server/active_record.rb +0 -23
data/lib/sidekiq/util.rb CHANGED
@@ -1,27 +1,67 @@
1
1
  # frozen_string_literal: true
2
- require 'socket'
3
- require 'securerandom'
4
- require 'sidekiq/exception_handler'
2
+
3
+ require "forwardable"
4
+ require "socket"
5
+ require "securerandom"
6
+ require "sidekiq/exception_handler"
5
7
 
6
8
  module Sidekiq
7
9
  ##
8
10
  # This module is part of Sidekiq core and not intended for extensions.
9
11
  #
12
+
13
+ class RingBuffer
14
+ include Enumerable
15
+ extend Forwardable
16
+ def_delegators :@buf, :[], :each, :size
17
+
18
+ def initialize(size, default = 0)
19
+ @size = size
20
+ @buf = Array.new(size, default)
21
+ @index = 0
22
+ end
23
+
24
+ def <<(element)
25
+ @buf[@index % @size] = element
26
+ @index += 1
27
+ element
28
+ end
29
+
30
+ def buffer
31
+ @buf
32
+ end
33
+
34
+ def reset(default = 0)
35
+ @buf.fill(default)
36
+ end
37
+ end
38
+
10
39
  module Util
11
40
  include ExceptionHandler
12
41
 
13
- EXPIRY = 60 * 60 * 24
42
+ # hack for quicker development / testing environment #2774
43
+ PAUSE_TIME = $stdout.tty? ? 0.1 : 0.5
44
+
45
+ # Wait for the orblock to be true or the deadline passed.
46
+ def wait_for(deadline, &condblock)
47
+ remaining = deadline - ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
48
+ while remaining > PAUSE_TIME
49
+ return if condblock.call
50
+ sleep PAUSE_TIME
51
+ remaining = deadline - ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
52
+ end
53
+ end
14
54
 
15
55
  def watchdog(last_words)
16
56
  yield
17
57
  rescue Exception => ex
18
- handle_exception(ex, { context: last_words })
58
+ handle_exception(ex, {context: last_words})
19
59
  raise ex
20
60
  end
21
61
 
22
62
  def safe_thread(name, &block)
23
63
  Thread.new do
24
- Thread.current['sidekiq_label'] = name
64
+ Thread.current.name = name
25
65
  watchdog(name, &block)
26
66
  end
27
67
  end
@@ -34,8 +74,12 @@ module Sidekiq
34
74
  Sidekiq.redis(&block)
35
75
  end
36
76
 
77
+ def tid
78
+ Thread.current["sidekiq_tid"] ||= (Thread.current.object_id ^ ::Process.pid).to_s(36)
79
+ end
80
+
37
81
  def hostname
38
- ENV['DYNO'] || Socket.gethostname
82
+ ENV["DYNO"] || Socket.gethostname
39
83
  end
40
84
 
41
85
  def process_nonce
@@ -43,22 +87,20 @@ module Sidekiq
43
87
  end
44
88
 
45
89
  def identity
46
- @@identity ||= "#{hostname}:#{$$}:#{process_nonce}"
90
+ @@identity ||= "#{hostname}:#{::Process.pid}:#{process_nonce}"
47
91
  end
48
92
 
49
- def fire_event(event, options={})
93
+ def fire_event(event, options = {})
50
94
  reverse = options[:reverse]
51
95
  reraise = options[:reraise]
52
96
 
53
97
  arr = Sidekiq.options[:lifecycle_events][event]
54
98
  arr.reverse! if reverse
55
99
  arr.each do |block|
56
- begin
57
- block.call
58
- rescue => ex
59
- handle_exception(ex, { context: "Exception during Sidekiq lifecycle event.", event: event })
60
- raise ex if reraise
61
- end
100
+ block.call
101
+ rescue => ex
102
+ handle_exception(ex, {context: "Exception during Sidekiq lifecycle event.", event: event})
103
+ raise ex if reraise
62
104
  end
63
105
  arr.clear
64
106
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Sidekiq
3
- VERSION = "5.2.1"
4
+ VERSION = "6.4.0"
4
5
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Sidekiq
4
4
  class WebAction
5
- RACK_SESSION = 'rack.session'
5
+ RACK_SESSION = "rack.session"
6
6
 
7
7
  attr_accessor :env, :block, :type
8
8
 
@@ -15,18 +15,18 @@ module Sidekiq
15
15
  end
16
16
 
17
17
  def halt(res)
18
- throw :halt, res
18
+ throw :halt, [res, {"Content-Type" => "text/plain"}, [res.to_s]]
19
19
  end
20
20
 
21
21
  def redirect(location)
22
- throw :halt, [302, { "Location" => "#{request.base_url}#{location}" }, []]
22
+ throw :halt, [302, {"Location" => "#{request.base_url}#{location}"}, []]
23
23
  end
24
24
 
25
25
  def params
26
- indifferent_hash = Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
26
+ indifferent_hash = Hash.new { |hash, key| hash[key.to_s] if Symbol === key }
27
27
 
28
28
  indifferent_hash.merge! request.params
29
- route_params.each {|k,v| indifferent_hash[k.to_s] = v }
29
+ route_params.each { |k, v| indifferent_hash[k.to_s] = v }
30
30
 
31
31
  indifferent_hash
32
32
  end
@@ -40,10 +40,14 @@ module Sidekiq
40
40
  end
41
41
 
42
42
  def erb(content, options = {})
43
- if content.kind_of? Symbol
43
+ if content.is_a? Symbol
44
44
  unless respond_to?(:"_erb_#{content}")
45
45
  src = ERB.new(File.read("#{Web.settings.views}/#{content}.erb")).src
46
- WebAction.class_eval("def _erb_#{content}\n#{src}\n end")
46
+ WebAction.class_eval <<-RUBY, __FILE__, __LINE__ + 1
47
+ def _erb_#{content}
48
+ #{src}
49
+ end
50
+ RUBY
47
51
  end
48
52
  end
49
53
 
@@ -64,22 +68,22 @@ module Sidekiq
64
68
  end
65
69
 
66
70
  def json(payload)
67
- [200, { "Content-Type" => "application/json", "Cache-Control" => "no-cache" }, [Sidekiq.dump_json(payload)]]
71
+ [200, {"Content-Type" => "application/json", "Cache-Control" => "private, no-store"}, [Sidekiq.dump_json(payload)]]
68
72
  end
69
73
 
70
74
  def initialize(env, block)
71
75
  @_erb = false
72
76
  @env = env
73
77
  @block = block
74
- @@files ||= {}
78
+ @files ||= {}
75
79
  end
76
80
 
77
81
  private
78
82
 
79
83
  def _erb(file, locals)
80
- locals.each {|k, v| define_singleton_method(k){ v } unless (singleton_methods.include? k)} if locals
84
+ locals&.each { |k, v| define_singleton_method(k) { v } unless singleton_methods.include? k }
81
85
 
82
- if file.kind_of?(String)
86
+ if file.is_a?(String)
83
87
  ERB.new(file).result(binding)
84
88
  else
85
89
  send(:"_erb_#{file}")
@@ -4,9 +4,7 @@ module Sidekiq
4
4
  class WebApplication
5
5
  extend WebRouter
6
6
 
7
- CONTENT_LENGTH = "Content-Length"
8
- CONTENT_TYPE = "Content-Type"
9
- REDIS_KEYS = %w(redis_version uptime_in_days connected_clients used_memory_human used_memory_peak_human)
7
+ REDIS_KEYS = %w[redis_version uptime_in_days connected_clients used_memory_human used_memory_peak_human]
10
8
  CSP_HEADER = [
11
9
  "default-src 'self' https: http:",
12
10
  "child-src 'self'",
@@ -17,11 +15,11 @@ module Sidekiq
17
15
  "manifest-src 'self'",
18
16
  "media-src 'self'",
19
17
  "object-src 'none'",
20
- "script-src 'self' https: http:",
18
+ "script-src 'self' https: http: 'unsafe-inline'",
21
19
  "style-src 'self' https: http: 'unsafe-inline'",
22
20
  "worker-src 'self'",
23
21
  "base-uri 'self'"
24
- ].join('; ').freeze
22
+ ].join("; ").freeze
25
23
 
26
24
  def initialize(klass)
27
25
  @klass = klass
@@ -43,9 +41,19 @@ module Sidekiq
43
41
  # nothing, backwards compatibility
44
42
  end
45
43
 
44
+ head "/" do
45
+ # HEAD / is the cheapest heartbeat possible,
46
+ # it hits Redis to ensure connectivity
47
+ Sidekiq.redis { |c| c.llen("queue:default") }
48
+ ""
49
+ end
50
+
46
51
  get "/" do
47
- @redis_info = redis_info.select{ |k, v| REDIS_KEYS.include? k }
48
- stats_history = Sidekiq::Stats::History.new((params['days'] || 30).to_i)
52
+ @redis_info = redis_info.select { |k, v| REDIS_KEYS.include? k }
53
+ days = (params["days"] || 30).to_i
54
+ return halt(401) if days < 1 || days > 180
55
+
56
+ stats_history = Sidekiq::Stats::History.new(days)
49
57
  @processed_history = stats_history.processed
50
58
  @failed_history = stats_history.failed
51
59
 
@@ -57,14 +65,14 @@ module Sidekiq
57
65
  end
58
66
 
59
67
  post "/busy" do
60
- if params['identity']
61
- p = Sidekiq::Process.new('identity' => params['identity'])
62
- p.quiet! if params['quiet']
63
- p.stop! if params['stop']
68
+ if params["identity"]
69
+ p = Sidekiq::Process.new("identity" => params["identity"])
70
+ p.quiet! if params["quiet"]
71
+ p.stop! if params["stop"]
64
72
  else
65
73
  processes.each do |pro|
66
- pro.quiet! if params['quiet']
67
- pro.stop! if params['stop']
74
+ pro.quiet! if params["quiet"]
75
+ pro.stop! if params["stop"]
68
76
  end
69
77
  end
70
78
 
@@ -77,42 +85,53 @@ module Sidekiq
77
85
  erb(:queues)
78
86
  end
79
87
 
88
+ QUEUE_NAME = /\A[a-z_:.\-0-9]+\z/i
89
+
80
90
  get "/queues/:name" do
81
91
  @name = route_params[:name]
82
92
 
83
- halt(404) unless @name
93
+ halt(404) if !@name || @name !~ QUEUE_NAME
84
94
 
85
- @count = (params['count'] || 25).to_i
95
+ @count = (params["count"] || 25).to_i
86
96
  @queue = Sidekiq::Queue.new(@name)
87
- (@current_page, @total_size, @messages) = page("queue:#{@name}", params['page'], @count)
88
- @messages = @messages.map { |msg| Sidekiq::Job.new(msg, @name) }
97
+ (@current_page, @total_size, @jobs) = page("queue:#{@name}", params["page"], @count, reverse: params["direction"] == "asc")
98
+ @jobs = @jobs.map { |msg| Sidekiq::JobRecord.new(msg, @name) }
89
99
 
90
100
  erb(:queue)
91
101
  end
92
102
 
93
103
  post "/queues/:name" do
94
- Sidekiq::Queue.new(route_params[:name]).clear
104
+ queue = Sidekiq::Queue.new(route_params[:name])
105
+
106
+ if Sidekiq.pro? && params["pause"]
107
+ queue.pause!
108
+ elsif Sidekiq.pro? && params["unpause"]
109
+ queue.unpause!
110
+ else
111
+ queue.clear
112
+ end
95
113
 
96
114
  redirect "#{root_path}queues"
97
115
  end
98
116
 
99
117
  post "/queues/:name/delete" do
100
118
  name = route_params[:name]
101
- Sidekiq::Job.new(params['key_val'], name).delete
119
+ Sidekiq::JobRecord.new(params["key_val"], name).delete
102
120
 
103
121
  redirect_with_query("#{root_path}queues/#{CGI.escape(name)}")
104
122
  end
105
123
 
106
- get '/morgue' do
107
- @count = (params['count'] || 25).to_i
108
- (@current_page, @total_size, @dead) = page("dead", params['page'], @count, reverse: true)
124
+ get "/morgue" do
125
+ @count = (params["count"] || 25).to_i
126
+ (@current_page, @total_size, @dead) = page("dead", params["page"], @count, reverse: true)
109
127
  @dead = @dead.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
110
128
 
111
129
  erb(:morgue)
112
130
  end
113
131
 
114
132
  get "/morgue/:key" do
115
- halt(404) unless key = route_params[:key]
133
+ key = route_params[:key]
134
+ halt(404) unless key
116
135
 
117
136
  @dead = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
118
137
 
@@ -123,10 +142,10 @@ module Sidekiq
123
142
  end
124
143
  end
125
144
 
126
- post '/morgue' do
127
- redirect(request.path) unless params['key']
145
+ post "/morgue" do
146
+ redirect(request.path) unless params["key"]
128
147
 
129
- params['key'].each do |key|
148
+ params["key"].each do |key|
130
149
  job = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
131
150
  retry_or_delete_or_kill job, params if job
132
151
  end
@@ -147,7 +166,8 @@ module Sidekiq
147
166
  end
148
167
 
149
168
  post "/morgue/:key" do
150
- halt(404) unless key = route_params[:key]
169
+ key = route_params[:key]
170
+ halt(404) unless key
151
171
 
152
172
  job = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
153
173
  retry_or_delete_or_kill job, params if job
@@ -155,9 +175,9 @@ module Sidekiq
155
175
  redirect_with_query("#{root_path}morgue")
156
176
  end
157
177
 
158
- get '/retries' do
159
- @count = (params['count'] || 25).to_i
160
- (@current_page, @total_size, @retries) = page("retry", params['page'], @count)
178
+ get "/retries" do
179
+ @count = (params["count"] || 25).to_i
180
+ (@current_page, @total_size, @retries) = page("retry", params["page"], @count)
161
181
  @retries = @retries.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
162
182
 
163
183
  erb(:retries)
@@ -173,10 +193,10 @@ module Sidekiq
173
193
  end
174
194
  end
175
195
 
176
- post '/retries' do
177
- redirect(request.path) unless params['key']
196
+ post "/retries" do
197
+ redirect(request.path) unless params["key"]
178
198
 
179
- params['key'].each do |key|
199
+ params["key"].each do |key|
180
200
  job = Sidekiq::RetrySet.new.fetch(*parse_params(key)).first
181
201
  retry_or_delete_or_kill job, params if job
182
202
  end
@@ -196,6 +216,12 @@ module Sidekiq
196
216
  redirect "#{root_path}retries"
197
217
  end
198
218
 
219
+ post "/retries/all/kill" do
220
+ Sidekiq::RetrySet.new.kill_all
221
+
222
+ redirect "#{root_path}retries"
223
+ end
224
+
199
225
  post "/retries/:key" do
200
226
  job = Sidekiq::RetrySet.new.fetch(*parse_params(route_params[:key])).first
201
227
 
@@ -204,9 +230,9 @@ module Sidekiq
204
230
  redirect_with_query("#{root_path}retries")
205
231
  end
206
232
 
207
- get '/scheduled' do
208
- @count = (params['count'] || 25).to_i
209
- (@current_page, @total_size, @scheduled) = page("schedule", params['page'], @count)
233
+ get "/scheduled" do
234
+ @count = (params["count"] || 25).to_i
235
+ (@current_page, @total_size, @scheduled) = page("schedule", params["page"], @count)
210
236
  @scheduled = @scheduled.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
211
237
 
212
238
  erb(:scheduled)
@@ -222,10 +248,10 @@ module Sidekiq
222
248
  end
223
249
  end
224
250
 
225
- post '/scheduled' do
226
- redirect(request.path) unless params['key']
251
+ post "/scheduled" do
252
+ redirect(request.path) unless params["key"]
227
253
 
228
- params['key'].each do |key|
254
+ params["key"].each do |key|
229
255
  job = Sidekiq::ScheduledSet.new.fetch(*parse_params(key)).first
230
256
  delete_or_add_queue job, params if job
231
257
  end
@@ -234,7 +260,8 @@ module Sidekiq
234
260
  end
235
261
 
236
262
  post "/scheduled/:key" do
237
- halt(404) unless key = route_params[:key]
263
+ key = route_params[:key]
264
+ halt(404) unless key
238
265
 
239
266
  job = Sidekiq::ScheduledSet.new.fetch(*parse_params(key)).first
240
267
  delete_or_add_queue job, params if job
@@ -242,23 +269,23 @@ module Sidekiq
242
269
  redirect_with_query("#{root_path}scheduled")
243
270
  end
244
271
 
245
- get '/dashboard/stats' do
272
+ get "/dashboard/stats" do
246
273
  redirect "#{root_path}stats"
247
274
  end
248
275
 
249
- get '/stats' do
276
+ get "/stats" do
250
277
  sidekiq_stats = Sidekiq::Stats.new
251
- redis_stats = redis_info.select { |k, v| REDIS_KEYS.include? k }
278
+ redis_stats = redis_info.select { |k, v| REDIS_KEYS.include? k }
252
279
  json(
253
280
  sidekiq: {
254
- processed: sidekiq_stats.processed,
255
- failed: sidekiq_stats.failed,
256
- busy: sidekiq_stats.workers_size,
257
- processes: sidekiq_stats.processes_size,
258
- enqueued: sidekiq_stats.enqueued,
259
- scheduled: sidekiq_stats.scheduled_size,
260
- retries: sidekiq_stats.retry_size,
261
- dead: sidekiq_stats.dead_size,
281
+ processed: sidekiq_stats.processed,
282
+ failed: sidekiq_stats.failed,
283
+ busy: sidekiq_stats.workers_size,
284
+ processes: sidekiq_stats.processes_size,
285
+ enqueued: sidekiq_stats.enqueued,
286
+ scheduled: sidekiq_stats.scheduled_size,
287
+ retries: sidekiq_stats.retry_size,
288
+ dead: sidekiq_stats.dead_size,
262
289
  default_latency: sidekiq_stats.default_queue_latency
263
290
  },
264
291
  redis: redis_stats,
@@ -266,60 +293,52 @@ module Sidekiq
266
293
  )
267
294
  end
268
295
 
269
- get '/stats/queues' do
296
+ get "/stats/queues" do
270
297
  json Sidekiq::Stats::Queues.new.lengths
271
298
  end
272
299
 
273
300
  def call(env)
274
301
  action = self.class.match(env)
275
- return [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass" }, ["Not Found"]] unless action
302
+ return [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found"]] unless action
276
303
 
304
+ app = @klass
277
305
  resp = catch(:halt) do
278
- app = @klass
279
306
  self.class.run_befores(app, action)
280
- begin
281
- resp = action.instance_exec env, &action.block
282
- ensure
283
- self.class.run_afters(app, action)
284
- end
285
-
286
- resp
307
+ action.instance_exec env, &action.block
308
+ ensure
309
+ self.class.run_afters(app, action)
287
310
  end
288
311
 
289
- resp = case resp
312
+ case resp
290
313
  when Array
314
+ # redirects go here
291
315
  resp
292
316
  else
317
+ # rendered content goes here
293
318
  headers = {
294
319
  "Content-Type" => "text/html",
295
- "Cache-Control" => "no-cache",
320
+ "Cache-Control" => "private, no-store",
296
321
  "Content-Language" => action.locale,
297
322
  "Content-Security-Policy" => CSP_HEADER
298
323
  }
299
-
324
+ # we'll let Rack calculate Content-Length for us.
300
325
  [200, headers, [resp]]
301
326
  end
302
-
303
- resp[1] = resp[1].dup
304
-
305
- resp[1][CONTENT_LENGTH] = resp[2].inject(0) { |l, p| l + p.bytesize }.to_s
306
-
307
- resp
308
327
  end
309
328
 
310
- def self.helpers(mod=nil, &block)
311
- if block_given?
329
+ def self.helpers(mod = nil, &block)
330
+ if block
312
331
  WebAction.class_eval(&block)
313
332
  else
314
333
  WebAction.send(:include, mod)
315
334
  end
316
335
  end
317
336
 
318
- def self.before(path=nil, &block)
337
+ def self.before(path = nil, &block)
319
338
  befores << [path && Regexp.new("\\A#{path.gsub("*", ".*")}\\z"), block]
320
339
  end
321
340
 
322
- def self.after(path=nil, &block)
341
+ def self.after(path = nil, &block)
323
342
  afters << [path && Regexp.new("\\A#{path.gsub("*", ".*")}\\z"), block]
324
343
  end
325
344
 
@@ -332,8 +351,8 @@ module Sidekiq
332
351
  end
333
352
 
334
353
  def self.run_hooks(hooks, app, action)
335
- hooks.select { |p,_| !p || p =~ action.env[WebRouter::PATH_INFO] }.
336
- each {|_,b| action.instance_exec(action.env, app, &b) }
354
+ hooks.select { |p, _| !p || p =~ action.env[WebRouter::PATH_INFO] }
355
+ .each { |_, b| action.instance_exec(action.env, app, &b) }
337
356
  end
338
357
 
339
358
  def self.befores