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.
- checksums.yaml +5 -5
- data/Changes.md +368 -1
- data/LICENSE +3 -3
- data/README.md +21 -37
- data/bin/sidekiq +26 -2
- data/bin/sidekiqload +33 -25
- data/bin/sidekiqmon +8 -0
- data/lib/generators/sidekiq/job_generator.rb +57 -0
- data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
- data/lib/generators/sidekiq/templates/{worker_spec.rb.erb → job_spec.rb.erb} +1 -1
- data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
- data/lib/sidekiq/api.rb +316 -246
- data/lib/sidekiq/cli.rb +195 -221
- data/lib/sidekiq/client.rb +42 -60
- data/lib/sidekiq/delay.rb +7 -6
- data/lib/sidekiq/exception_handler.rb +10 -12
- data/lib/sidekiq/extensions/action_mailer.rb +15 -24
- data/lib/sidekiq/extensions/active_record.rb +15 -12
- data/lib/sidekiq/extensions/class_methods.rb +16 -13
- data/lib/sidekiq/extensions/generic_proxy.rb +8 -6
- data/lib/sidekiq/fetch.rb +39 -31
- data/lib/sidekiq/job.rb +13 -0
- data/lib/sidekiq/job_logger.rb +47 -9
- data/lib/sidekiq/job_retry.rb +88 -68
- data/lib/sidekiq/job_util.rb +65 -0
- data/lib/sidekiq/launcher.rb +151 -61
- data/lib/sidekiq/logger.rb +166 -0
- data/lib/sidekiq/manager.rb +18 -22
- data/lib/sidekiq/middleware/chain.rb +20 -8
- data/lib/sidekiq/middleware/current_attributes.rb +57 -0
- data/lib/sidekiq/middleware/i18n.rb +5 -7
- data/lib/sidekiq/monitor.rb +133 -0
- data/lib/sidekiq/paginator.rb +18 -14
- data/lib/sidekiq/processor.rb +116 -82
- data/lib/sidekiq/rails.rb +42 -38
- data/lib/sidekiq/redis_connection.rb +49 -30
- data/lib/sidekiq/scheduled.rb +62 -28
- data/lib/sidekiq/sd_notify.rb +149 -0
- data/lib/sidekiq/systemd.rb +24 -0
- data/lib/sidekiq/testing/inline.rb +2 -1
- data/lib/sidekiq/testing.rb +36 -27
- data/lib/sidekiq/util.rb +57 -15
- data/lib/sidekiq/version.rb +2 -1
- data/lib/sidekiq/web/action.rb +15 -11
- data/lib/sidekiq/web/application.rb +95 -76
- data/lib/sidekiq/web/csrf_protection.rb +180 -0
- data/lib/sidekiq/web/helpers.rb +115 -91
- data/lib/sidekiq/web/router.rb +23 -19
- data/lib/sidekiq/web.rb +61 -105
- data/lib/sidekiq/worker.rb +259 -99
- data/lib/sidekiq.rb +79 -45
- data/sidekiq.gemspec +23 -18
- data/web/assets/images/apple-touch-icon.png +0 -0
- data/web/assets/javascripts/application.js +83 -64
- data/web/assets/javascripts/dashboard.js +66 -75
- data/web/assets/stylesheets/application-dark.css +143 -0
- data/web/assets/stylesheets/application-rtl.css +0 -4
- data/web/assets/stylesheets/application.css +75 -231
- data/web/assets/stylesheets/bootstrap.css +1 -1
- data/web/locales/ar.yml +9 -2
- data/web/locales/de.yml +14 -2
- data/web/locales/en.yml +7 -1
- data/web/locales/es.yml +18 -2
- data/web/locales/fr.yml +10 -3
- data/web/locales/ja.yml +7 -1
- data/web/locales/lt.yml +83 -0
- data/web/locales/pl.yml +4 -4
- data/web/locales/ru.yml +4 -0
- data/web/locales/vi.yml +83 -0
- data/web/views/_footer.erb +1 -1
- data/web/views/_job_info.erb +3 -2
- data/web/views/_nav.erb +3 -17
- data/web/views/_poll_link.erb +2 -5
- data/web/views/_summary.erb +7 -7
- data/web/views/busy.erb +54 -20
- data/web/views/dashboard.erb +22 -14
- data/web/views/dead.erb +3 -3
- data/web/views/layout.erb +3 -1
- data/web/views/morgue.erb +9 -6
- data/web/views/queue.erb +20 -10
- data/web/views/queues.erb +11 -3
- data/web/views/retries.erb +14 -7
- data/web/views/retry.erb +3 -3
- data/web/views/scheduled.erb +5 -2
- metadata +39 -54
- data/.github/contributing.md +0 -32
- data/.github/issue_template.md +0 -11
- data/.gitignore +0 -13
- data/.travis.yml +0 -14
- data/3.0-Upgrade.md +0 -70
- data/4.0-Upgrade.md +0 -53
- data/5.0-Upgrade.md +0 -56
- data/COMM-LICENSE +0 -95
- data/Ent-Changes.md +0 -221
- data/Gemfile +0 -14
- data/Pro-2.0-Upgrade.md +0 -138
- data/Pro-3.0-Upgrade.md +0 -44
- data/Pro-4.0-Upgrade.md +0 -35
- data/Pro-Changes.md +0 -739
- data/Rakefile +0 -8
- data/bin/sidekiqctl +0 -99
- data/code_of_conduct.md +0 -50
- data/lib/generators/sidekiq/worker_generator.rb +0 -49
- data/lib/sidekiq/core_ext.rb +0 -1
- data/lib/sidekiq/logging.rb +0 -122
- data/lib/sidekiq/middleware/server/active_record.rb +0 -23
data/lib/sidekiq/util.rb
CHANGED
@@ -1,27 +1,67 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
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
|
-
|
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, {
|
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
|
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[
|
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}:#{
|
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
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web/action.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Sidekiq
|
4
4
|
class WebAction
|
5
|
-
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, {
|
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.
|
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
|
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, {
|
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
|
-
|
78
|
+
@files ||= {}
|
75
79
|
end
|
76
80
|
|
77
81
|
private
|
78
82
|
|
79
83
|
def _erb(file, locals)
|
80
|
-
locals
|
84
|
+
locals&.each { |k, v| define_singleton_method(k) { v } unless singleton_methods.include? k }
|
81
85
|
|
82
|
-
if file.
|
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
|
-
|
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(
|
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
|
-
|
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[
|
61
|
-
p = Sidekiq::Process.new(
|
62
|
-
p.quiet! if params[
|
63
|
-
p.stop! if params[
|
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[
|
67
|
-
pro.stop! if params[
|
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)
|
93
|
+
halt(404) if !@name || @name !~ QUEUE_NAME
|
84
94
|
|
85
|
-
@count = (params[
|
95
|
+
@count = (params["count"] || 25).to_i
|
86
96
|
@queue = Sidekiq::Queue.new(@name)
|
87
|
-
(@current_page, @total_size, @
|
88
|
-
@
|
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])
|
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::
|
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
|
107
|
-
@count = (params[
|
108
|
-
(@current_page, @total_size, @dead) = page("dead", params[
|
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
|
-
|
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
|
127
|
-
redirect(request.path) unless params[
|
145
|
+
post "/morgue" do
|
146
|
+
redirect(request.path) unless params["key"]
|
128
147
|
|
129
|
-
params[
|
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
|
-
|
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
|
159
|
-
@count = (params[
|
160
|
-
(@current_page, @total_size, @retries) = page("retry", params[
|
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
|
177
|
-
redirect(request.path) unless params[
|
196
|
+
post "/retries" do
|
197
|
+
redirect(request.path) unless params["key"]
|
178
198
|
|
179
|
-
params[
|
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
|
208
|
-
@count = (params[
|
209
|
-
(@current_page, @total_size, @scheduled) = page("schedule", params[
|
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
|
226
|
-
redirect(request.path) unless params[
|
251
|
+
post "/scheduled" do
|
252
|
+
redirect(request.path) unless params["key"]
|
227
253
|
|
228
|
-
params[
|
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
|
-
|
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
|
272
|
+
get "/dashboard/stats" do
|
246
273
|
redirect "#{root_path}stats"
|
247
274
|
end
|
248
275
|
|
249
|
-
get
|
276
|
+
get "/stats" do
|
250
277
|
sidekiq_stats = Sidekiq::Stats.new
|
251
|
-
redis_stats
|
278
|
+
redis_stats = redis_info.select { |k, v| REDIS_KEYS.include? k }
|
252
279
|
json(
|
253
280
|
sidekiq: {
|
254
|
-
processed:
|
255
|
-
failed:
|
256
|
-
busy:
|
257
|
-
processes:
|
258
|
-
enqueued:
|
259
|
-
scheduled:
|
260
|
-
retries:
|
261
|
-
dead:
|
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
|
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"
|
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
|
-
|
281
|
-
|
282
|
-
|
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
|
-
|
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-
|
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
|
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
|
-
|
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
|