sidekiq 2.5.4 → 2.6.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.
- data/.travis.yml +2 -0
- data/Changes.md +10 -0
- data/examples/sinkiq.rb +3 -2
- data/lib/sidekiq/api.rb +135 -6
- data/lib/sidekiq/capistrano.rb +5 -3
- data/lib/sidekiq/cli.rb +23 -6
- data/lib/sidekiq/logging.rb +8 -7
- data/lib/sidekiq/processor.rb +2 -0
- data/lib/sidekiq/stats.rb +1 -24
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +63 -79
- data/test/config.yml +1 -0
- data/test/test_api.rb +189 -5
- data/test/test_cli.rb +46 -0
- data/test/test_processor.rb +53 -0
- data/test/test_sidekiq.rb +14 -0
- data/test/test_stats.rb +0 -60
- data/test/test_web.rb +63 -53
- data/web/assets/javascripts/application.js +24 -66
- data/web/assets/javascripts/dashboard.js +110 -0
- data/web/assets/stylesheets/application.css +402 -258
- data/web/assets/stylesheets/bootstrap.css +1 -1
- data/web/views/_nav.slim +8 -13
- data/web/views/_summary.slim +6 -6
- data/web/views/dashboard.slim +36 -0
- data/web/views/layout.slim +22 -21
- data/web/views/queue.slim +3 -3
- data/web/views/queues.slim +13 -17
- data/web/views/retries.slim +3 -3
- data/web/views/retry.slim +46 -43
- data/web/views/scheduled.slim +2 -2
- metadata +6 -6
- data/web/assets/javascripts/vendor/bootstrap.js +0 -7
- data/web/assets/javascripts/vendor/jquery.js +0 -3
- data/web/assets/javascripts/vendor/jquery.timeago.js +0 -148
- data/web/views/poll.slim +0 -4
data/.travis.yml
CHANGED
data/Changes.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
2.6.0
|
2
|
+
-----------
|
3
|
+
|
4
|
+
- Web UI much more mobile friendly now [brandonhilkert, #573]
|
5
|
+
- Enable live polling for every section in Web UI [brandonhilkert, #567]
|
6
|
+
- Add Stats API [brandonhilkert, #565]
|
7
|
+
- Add Stats::History API [brandonhilkert, #570]
|
8
|
+
- Add Dashboard to Web UI with live and historical stat graphs [brandonhilkert, #580]
|
9
|
+
- Add option to log output to a file, reopen log file on USR2 signal [mrnugget, #581]
|
10
|
+
|
1
11
|
2.5.4
|
2
12
|
-----------
|
3
13
|
|
data/examples/sinkiq.rb
CHANGED
@@ -19,8 +19,9 @@ class SinatraWorker
|
|
19
19
|
end
|
20
20
|
|
21
21
|
get '/' do
|
22
|
-
|
23
|
-
@
|
22
|
+
stats = Sidekiq::Stats.new
|
23
|
+
@failed = stats.failed
|
24
|
+
@processed = stats.processed
|
24
25
|
@messages = $redis.lrange('sinkiq-example-messages', 0, -1)
|
25
26
|
erb :index
|
26
27
|
end
|
data/lib/sidekiq/api.rb
CHANGED
@@ -1,6 +1,91 @@
|
|
1
1
|
require 'sidekiq'
|
2
2
|
|
3
3
|
module Sidekiq
|
4
|
+
class Stats
|
5
|
+
def processed
|
6
|
+
count = Sidekiq.redis do |conn|
|
7
|
+
conn.get("stat:processed")
|
8
|
+
end
|
9
|
+
count.nil? ? 0 : count.to_i
|
10
|
+
end
|
11
|
+
|
12
|
+
def failed
|
13
|
+
count = Sidekiq.redis do |conn|
|
14
|
+
conn.get("stat:failed")
|
15
|
+
end
|
16
|
+
count.nil? ? 0 : count.to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
def queues
|
20
|
+
Sidekiq.redis do |conn|
|
21
|
+
queues = conn.smembers('queues')
|
22
|
+
|
23
|
+
array_of_arrays = queues.inject({}) do |memo, queue|
|
24
|
+
memo[queue] = conn.llen("queue:#{queue}")
|
25
|
+
memo
|
26
|
+
end.sort_by { |_, size| size }
|
27
|
+
|
28
|
+
Hash[array_of_arrays.reverse]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def enqueued
|
33
|
+
queues.values.inject(&:+) || 0
|
34
|
+
end
|
35
|
+
|
36
|
+
class History
|
37
|
+
def initialize(days_previous, start_date = nil)
|
38
|
+
@days_previous = days_previous
|
39
|
+
@start_date = start_date || Time.now.utc.to_date
|
40
|
+
end
|
41
|
+
|
42
|
+
def processed
|
43
|
+
date_stat_hash("processed")
|
44
|
+
end
|
45
|
+
|
46
|
+
def failed
|
47
|
+
date_stat_hash("failed")
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.cleanup
|
51
|
+
days_of_stats_to_keep = 180
|
52
|
+
today = Time.now.utc.to_date
|
53
|
+
delete_before_date = Time.now.utc.to_date - days_of_stats_to_keep
|
54
|
+
|
55
|
+
Sidekiq.redis do |conn|
|
56
|
+
processed_keys = conn.keys("stat:processed:*")
|
57
|
+
earliest = "stat:processed:#{delete_before_date.to_s}"
|
58
|
+
pkeys = processed_keys.select { |key| key < earliest }
|
59
|
+
conn.del(pkeys) if pkeys.size > 0
|
60
|
+
|
61
|
+
failed_keys = conn.keys("stat:failed:*")
|
62
|
+
earliest = "stat:failed:#{delete_before_date.to_s}"
|
63
|
+
fkeys = failed_keys.select { |key| key < earliest }
|
64
|
+
conn.del(fkeys) if fkeys.size > 0
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def date_stat_hash(stat)
|
71
|
+
i = 0
|
72
|
+
stat_hash = {}
|
73
|
+
|
74
|
+
Sidekiq.redis do |conn|
|
75
|
+
while i < @days_previous
|
76
|
+
date = @start_date - i
|
77
|
+
value = conn.get("stat:#{stat}:#{date}")
|
78
|
+
|
79
|
+
stat_hash[date.to_s] = value ? value.to_i : 0
|
80
|
+
|
81
|
+
i += 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
stat_hash
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
4
89
|
|
5
90
|
##
|
6
91
|
# Encapsulates a queue within Sidekiq.
|
@@ -110,11 +195,24 @@ module Sidekiq
|
|
110
195
|
end
|
111
196
|
|
112
197
|
def at
|
113
|
-
Time.at(
|
198
|
+
Time.at(score)
|
114
199
|
end
|
115
200
|
|
116
201
|
def delete
|
117
|
-
@parent.delete(
|
202
|
+
@parent.delete(score, jid)
|
203
|
+
end
|
204
|
+
|
205
|
+
def retry
|
206
|
+
raise "Retry not available on jobs not in the Retry queue." unless item["failed_at"]
|
207
|
+
Sidekiq.redis do |conn|
|
208
|
+
results = conn.zrangebyscore('retry', score, score)
|
209
|
+
conn.zremrangebyscore('retry', score, score)
|
210
|
+
results.map do |message|
|
211
|
+
msg = Sidekiq.load_json(message)
|
212
|
+
msg['retry_count'] = msg['retry_count'] - 1
|
213
|
+
conn.rpush("queue:#{msg['queue']}", Sidekiq.dump_json(msg))
|
214
|
+
end
|
215
|
+
end
|
118
216
|
end
|
119
217
|
end
|
120
218
|
|
@@ -146,11 +244,42 @@ module Sidekiq
|
|
146
244
|
end
|
147
245
|
end
|
148
246
|
|
149
|
-
def
|
150
|
-
|
151
|
-
conn.
|
247
|
+
def fetch(score, jid = nil)
|
248
|
+
elements = Sidekiq.redis do |conn|
|
249
|
+
conn.zrangebyscore(@zset, score, score)
|
250
|
+
end
|
251
|
+
|
252
|
+
elements.inject([]) do |result, element|
|
253
|
+
entry = SortedEntry.new(self, score, element)
|
254
|
+
if jid
|
255
|
+
result << entry if entry.jid == jid
|
256
|
+
else
|
257
|
+
result << entry
|
258
|
+
end
|
259
|
+
result
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def delete(score, jid = nil)
|
264
|
+
if jid
|
265
|
+
elements = Sidekiq.redis do |conn|
|
266
|
+
conn.zrangebyscore(@zset, score, score)
|
267
|
+
end
|
268
|
+
|
269
|
+
elements_with_jid = elements.map do |element|
|
270
|
+
message = Sidekiq.load_json(element)
|
271
|
+
|
272
|
+
if message["jid"] == jid
|
273
|
+
Sidekiq.redis { |conn| conn.zrem(@zset, element) }
|
274
|
+
end
|
275
|
+
end
|
276
|
+
elements_with_jid.count != 0
|
277
|
+
else
|
278
|
+
count = Sidekiq.redis do |conn|
|
279
|
+
conn.zremrangebyscore(@zset, score, score)
|
280
|
+
end
|
281
|
+
count != 0
|
152
282
|
end
|
153
|
-
count != 0
|
154
283
|
end
|
155
284
|
|
156
285
|
def clear
|
data/lib/sidekiq/capistrano.rb
CHANGED
@@ -4,6 +4,8 @@ Capistrano::Configuration.instance.load do
|
|
4
4
|
after "deploy:start", "sidekiq:start"
|
5
5
|
after "deploy:restart", "sidekiq:restart"
|
6
6
|
|
7
|
+
_cset(:sidekiq_cmd) { "#{fetch(:bundle_cmd, "bundle")} exec sidekiq" }
|
8
|
+
_cset(:sidekiqctl_cmd) { "#{fetch(:bundle_cmd, "bundle")} exec sidekiqctl" }
|
7
9
|
_cset(:sidekiq_timeout) { 10 }
|
8
10
|
_cset(:sidekiq_role) { :app }
|
9
11
|
_cset(:sidekiq_pid) { "#{current_path}/tmp/pids/sidekiq.pid" }
|
@@ -19,14 +21,14 @@ Capistrano::Configuration.instance.load do
|
|
19
21
|
desc "Quiet sidekiq (stop accepting new work)"
|
20
22
|
task :quiet, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
|
21
23
|
for_each_process do |pid_file|
|
22
|
-
run "if [ -d #{current_path} ] && [ -f #{pid_file} ]; then cd #{current_path} && #{fetch(:
|
24
|
+
run "if [ -d #{current_path} ] && [ -f #{pid_file} ]; then cd #{current_path} && #{fetch(:sidekiqctl_cmd)} quiet #{pid_file} ; fi"
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
26
28
|
desc "Stop sidekiq"
|
27
29
|
task :stop, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
|
28
30
|
for_each_process do |pid_file|
|
29
|
-
run "if [ -d #{current_path} ] && [ -f #{pid_file} ]; then cd #{current_path} && #{fetch(:
|
31
|
+
run "if [ -d #{current_path} ] && [ -f #{pid_file} ]; then cd #{current_path} && #{fetch(:sidekiqctl_cmd)} stop #{pid_file} #{fetch :sidekiq_timeout} ; fi"
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
@@ -34,7 +36,7 @@ Capistrano::Configuration.instance.load do
|
|
34
36
|
task :start, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
|
35
37
|
rails_env = fetch(:rails_env, "production")
|
36
38
|
for_each_process do |pid_file|
|
37
|
-
run "cd #{current_path} ; nohup #{fetch(:
|
39
|
+
run "cd #{current_path} ; nohup #{fetch(:sidekiq_cmd)} -e #{rails_env} -C #{current_path}/config/sidekiq.yml -P #{pid_file} >> #{current_path}/log/sidekiq.log 2>&1 &", :pty => false
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
data/lib/sidekiq/cli.rb
CHANGED
@@ -15,6 +15,13 @@ trap 'USR1' do
|
|
15
15
|
mgr.async.stop if mgr
|
16
16
|
end
|
17
17
|
|
18
|
+
trap 'USR2' do
|
19
|
+
if Sidekiq.options[:logfile]
|
20
|
+
Sidekiq.logger.info "Received USR2, reopening log file"
|
21
|
+
Sidekiq::Logging.initialize_logger(Sidekiq.options[:logfile])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
18
25
|
trap 'TTIN' do
|
19
26
|
Thread.list.each do |thread|
|
20
27
|
Sidekiq.logger.info "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
|
@@ -56,15 +63,12 @@ module Sidekiq
|
|
56
63
|
|
57
64
|
def parse(args=ARGV)
|
58
65
|
@code = nil
|
59
|
-
Sidekiq.logger
|
60
66
|
|
61
67
|
cli = parse_options(args)
|
62
68
|
config = parse_config(cli)
|
63
69
|
options.merge!(config.merge(cli))
|
64
70
|
|
65
|
-
|
66
|
-
Celluloid.logger = nil unless options[:verbose]
|
67
|
-
|
71
|
+
initialize_logger
|
68
72
|
validate!
|
69
73
|
write_pid
|
70
74
|
boot_system
|
@@ -75,6 +79,8 @@ module Sidekiq
|
|
75
79
|
logger.info "Running in #{RUBY_DESCRIPTION}"
|
76
80
|
logger.info Sidekiq::LICENSE
|
77
81
|
|
82
|
+
Sidekiq::Stats::History.cleanup
|
83
|
+
|
78
84
|
@manager = Sidekiq::Manager.new(options)
|
79
85
|
poller = Sidekiq::Scheduled::Poller.new
|
80
86
|
begin
|
@@ -166,8 +172,8 @@ module Sidekiq
|
|
166
172
|
parse_queues opts, queues_and_weights
|
167
173
|
end
|
168
174
|
|
169
|
-
o.on "-v", "--verbose", "Print more verbose output" do
|
170
|
-
|
175
|
+
o.on "-v", "--verbose", "Print more verbose output" do |arg|
|
176
|
+
opts[:verbose] = arg
|
171
177
|
end
|
172
178
|
|
173
179
|
o.on '-e', '--environment ENV', "Application environment" do |arg|
|
@@ -198,6 +204,10 @@ module Sidekiq
|
|
198
204
|
opts[:config_file] = arg
|
199
205
|
end
|
200
206
|
|
207
|
+
o.on '-L', '--logfile PATH', "path to writable logfile" do |arg|
|
208
|
+
opts[:logfile] = arg
|
209
|
+
end
|
210
|
+
|
201
211
|
o.on '-V', '--version', "Print version and exit" do |arg|
|
202
212
|
puts "Sidekiq #{Sidekiq::VERSION}"
|
203
213
|
die(0)
|
@@ -213,6 +223,13 @@ module Sidekiq
|
|
213
223
|
opts
|
214
224
|
end
|
215
225
|
|
226
|
+
def initialize_logger
|
227
|
+
Sidekiq::Logging.initialize_logger(options[:logfile]) if options[:logfile]
|
228
|
+
|
229
|
+
Sidekiq.logger.level = Logger::DEBUG if options[:verbose]
|
230
|
+
Celluloid.logger = nil unless options[:verbose]
|
231
|
+
end
|
232
|
+
|
216
233
|
def write_pid
|
217
234
|
if path = options[:pidfile]
|
218
235
|
File.open(path, 'w') do |f|
|
data/lib/sidekiq/logging.rb
CHANGED
@@ -25,13 +25,15 @@ module Sidekiq
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
+
def self.initialize_logger(log_target = STDOUT)
|
29
|
+
@logger = Logger.new(log_target)
|
30
|
+
@logger.level = Logger::INFO
|
31
|
+
@logger.formatter = Pretty.new
|
32
|
+
@logger
|
33
|
+
end
|
34
|
+
|
28
35
|
def self.logger
|
29
|
-
@logger
|
30
|
-
log = Logger.new(STDOUT)
|
31
|
-
log.level = Logger::INFO
|
32
|
-
log.formatter = Pretty.new
|
33
|
-
log
|
34
|
-
end
|
36
|
+
@logger || initialize_logger
|
35
37
|
end
|
36
38
|
|
37
39
|
def self.logger=(log)
|
@@ -41,6 +43,5 @@ module Sidekiq
|
|
41
43
|
def logger
|
42
44
|
Sidekiq::Logging.logger
|
43
45
|
end
|
44
|
-
|
45
46
|
end
|
46
47
|
end
|
data/lib/sidekiq/processor.rb
CHANGED
@@ -80,6 +80,7 @@ module Sidekiq
|
|
80
80
|
redis do |conn|
|
81
81
|
conn.multi do
|
82
82
|
conn.incrby("stat:failed", 1)
|
83
|
+
conn.incrby("stat:failed:#{Time.now.utc.to_date}", 1)
|
83
84
|
end
|
84
85
|
end
|
85
86
|
raise
|
@@ -90,6 +91,7 @@ module Sidekiq
|
|
90
91
|
conn.del("worker:#{self}")
|
91
92
|
conn.del("worker:#{self}:started")
|
92
93
|
conn.incrby("stat:processed", 1)
|
94
|
+
conn.incrby("stat:processed:#{Time.now.utc.to_date}", 1)
|
93
95
|
end
|
94
96
|
end
|
95
97
|
end
|
data/lib/sidekiq/stats.rb
CHANGED
@@ -1,31 +1,8 @@
|
|
1
1
|
module Sidekiq
|
2
2
|
module_function
|
3
3
|
|
4
|
-
def info
|
5
|
-
results = {}
|
6
|
-
processed, failed, queues = Sidekiq.redis { |conn|
|
7
|
-
conn.multi do
|
8
|
-
conn.get('stat:processed')
|
9
|
-
conn.get('stat:failed')
|
10
|
-
conn.smembers('queues')
|
11
|
-
end
|
12
|
-
}
|
13
|
-
results[:queues_with_sizes] = Sidekiq.redis do |conn|
|
14
|
-
queues.inject({}) { |memo, q|
|
15
|
-
memo[q] = conn.llen("queue:#{q}")
|
16
|
-
memo
|
17
|
-
}.sort_by { |_, size| size }
|
18
|
-
end
|
19
|
-
results[:processed] = (processed || 0).to_i
|
20
|
-
results[:failed] = (failed || 0).to_i
|
21
|
-
results[:backlog] = results[:queues_with_sizes].
|
22
|
-
map {|_, size| size }.
|
23
|
-
inject(0) {|memo, val| memo + val }
|
24
|
-
results
|
25
|
-
end
|
26
|
-
|
27
4
|
def size(*queues)
|
28
|
-
return
|
5
|
+
return Sidekiq::Stats.new.enqueued if queues.empty?
|
29
6
|
|
30
7
|
Sidekiq.redis { |conn|
|
31
8
|
conn.multi {
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web.rb
CHANGED
@@ -34,28 +34,16 @@ module Sidekiq
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
def
|
38
|
-
@
|
37
|
+
def stats
|
38
|
+
@stats ||= Sidekiq::Stats.new
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
42
|
-
|
41
|
+
def scheduled_job_count
|
42
|
+
Sidekiq::ScheduledSet.new.size
|
43
43
|
end
|
44
44
|
|
45
|
-
def
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
def zcard(name)
|
50
|
-
Sidekiq.redis { |conn| conn.zcard(name) }
|
51
|
-
end
|
52
|
-
|
53
|
-
def queues
|
54
|
-
@queues ||= Sidekiq.info[:queues_with_sizes]
|
55
|
-
end
|
56
|
-
|
57
|
-
def backlog
|
58
|
-
info[:backlog]
|
45
|
+
def retry_job_count
|
46
|
+
Sidekiq::RetrySet.new.size
|
59
47
|
end
|
60
48
|
|
61
49
|
def retries_with_score(score)
|
@@ -86,6 +74,15 @@ module Sidekiq
|
|
86
74
|
%{<time datetime="#{time.getutc.iso8601}">#{time}</time>}
|
87
75
|
end
|
88
76
|
|
77
|
+
def job_params(job, score)
|
78
|
+
"#{score}-#{job['jid']}"
|
79
|
+
end
|
80
|
+
|
81
|
+
def parse_params(params)
|
82
|
+
score, jid = params.split("-")
|
83
|
+
[score.to_f, jid]
|
84
|
+
end
|
85
|
+
|
89
86
|
def display_args(args, count=100)
|
90
87
|
args.map { |arg| a = arg.inspect; a.size > count ? "#{a[0..count]}..." : a }.join(", ")
|
91
88
|
end
|
@@ -112,12 +109,8 @@ module Sidekiq
|
|
112
109
|
slim :index
|
113
110
|
end
|
114
111
|
|
115
|
-
get "/poll" do
|
116
|
-
slim :poll, layout: false
|
117
|
-
end
|
118
|
-
|
119
112
|
get "/queues" do
|
120
|
-
@queues = queues
|
113
|
+
@queues = Sidekiq::Stats.new.queues
|
121
114
|
slim :queues
|
122
115
|
end
|
123
116
|
|
@@ -141,20 +134,10 @@ module Sidekiq
|
|
141
134
|
end
|
142
135
|
|
143
136
|
post "/queues/:name/delete" do
|
144
|
-
Sidekiq.
|
145
|
-
conn.lrem("queue:#{params[:name]}", 0, params[:key_val])
|
146
|
-
end
|
137
|
+
Sidekiq::Job.new(params[:key_val], params[:name]).delete
|
147
138
|
redirect "#{root_path}queues/#{params[:name]}"
|
148
139
|
end
|
149
140
|
|
150
|
-
get "/retries/:score" do
|
151
|
-
halt 404 unless params[:score]
|
152
|
-
@score = params[:score].to_f
|
153
|
-
@retries = retries_with_score(@score)
|
154
|
-
redirect "#{root_path}retries" if @retries.empty?
|
155
|
-
slim :retry
|
156
|
-
end
|
157
|
-
|
158
141
|
get '/retries' do
|
159
142
|
@count = (params[:count] || 25).to_i
|
160
143
|
(@current_page, @total_size, @retries) = page("retry", params[:page], @count)
|
@@ -162,31 +145,22 @@ module Sidekiq
|
|
162
145
|
slim :retries
|
163
146
|
end
|
164
147
|
|
165
|
-
get
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
slim :
|
170
|
-
end
|
171
|
-
|
172
|
-
post '/scheduled' do
|
173
|
-
halt 404 unless params[:score]
|
174
|
-
halt 404 unless params['delete']
|
175
|
-
params[:score].each do |score|
|
176
|
-
s = score.to_f
|
177
|
-
process_score('schedule', s, :delete)
|
178
|
-
end
|
179
|
-
redirect "#{root_path}scheduled"
|
148
|
+
get "/retries/:key" do
|
149
|
+
halt 404 unless params['key']
|
150
|
+
@retry = Sidekiq::RetrySet.new.fetch(*parse_params(params['key'])).first
|
151
|
+
redirect "#{root_path}retries" if @retry.nil?
|
152
|
+
slim :retry
|
180
153
|
end
|
181
154
|
|
182
155
|
post '/retries' do
|
183
|
-
halt 404 unless params[
|
184
|
-
|
185
|
-
|
156
|
+
halt 404 unless params['key']
|
157
|
+
|
158
|
+
params['key'].each do |key|
|
159
|
+
job = Sidekiq::RetrySet.new.fetch(*parse_params(key)).first
|
186
160
|
if params['retry']
|
187
|
-
|
161
|
+
job.retry
|
188
162
|
elsif params['delete']
|
189
|
-
|
163
|
+
job.delete
|
190
164
|
end
|
191
165
|
end
|
192
166
|
redirect "#{root_path}retries"
|
@@ -198,40 +172,49 @@ module Sidekiq
|
|
198
172
|
end
|
199
173
|
|
200
174
|
post "/retries/all/retry" do
|
201
|
-
Sidekiq::RetrySet.new.each
|
202
|
-
process_score('retry', job.score, :retry)
|
203
|
-
end
|
175
|
+
Sidekiq::RetrySet.new.each { |job| job.retry }
|
204
176
|
redirect "#{root_path}retries"
|
205
177
|
end
|
206
178
|
|
207
|
-
post "/retries/:
|
208
|
-
halt 404 unless params[
|
209
|
-
|
179
|
+
post "/retries/:key" do
|
180
|
+
halt 404 unless params['key']
|
181
|
+
job = Sidekiq::RetrySet.new.fetch(*parse_params(params['key'])).first
|
210
182
|
if params['retry']
|
211
|
-
|
183
|
+
job.retry
|
212
184
|
elsif params['delete']
|
213
|
-
|
185
|
+
job.delete
|
214
186
|
end
|
215
187
|
redirect "#{root_path}retries"
|
216
188
|
end
|
217
189
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
when :delete
|
231
|
-
Sidekiq.redis do |conn|
|
232
|
-
conn.zremrangebyscore(set, score, score)
|
233
|
-
end
|
190
|
+
get '/scheduled' do
|
191
|
+
@count = (params[:count] || 25).to_i
|
192
|
+
(@current_page, @total_size, @scheduled) = page("schedule", params[:page], @count)
|
193
|
+
@scheduled = @scheduled.map {|msg, score| [Sidekiq.load_json(msg), score] }
|
194
|
+
slim :scheduled
|
195
|
+
end
|
196
|
+
|
197
|
+
post '/scheduled' do
|
198
|
+
halt 404 unless params['key']
|
199
|
+
halt 404 unless params['delete']
|
200
|
+
params['key'].each do |key|
|
201
|
+
Sidekiq::ScheduledSet.new.fetch(*parse_params(key)).first.delete
|
234
202
|
end
|
203
|
+
redirect "#{root_path}scheduled"
|
204
|
+
end
|
205
|
+
|
206
|
+
get '/dashboard' do
|
207
|
+
@redis_info = Sidekiq.redis{ |conn| conn.info }
|
208
|
+
stats_history = Sidekiq::Stats::History.new((params[:days] || 30).to_i)
|
209
|
+
@processed_history = stats_history.processed
|
210
|
+
@failed_history = stats_history.failed
|
211
|
+
slim :dashboard
|
212
|
+
end
|
213
|
+
|
214
|
+
get '/dashboard/stats' do
|
215
|
+
stats = Sidekiq::Stats.new
|
216
|
+
content_type :json
|
217
|
+
Sidekiq.dump_json({ processed: stats.processed, failed: stats.failed })
|
235
218
|
end
|
236
219
|
|
237
220
|
def self.tabs
|
@@ -239,7 +222,8 @@ module Sidekiq
|
|
239
222
|
"Workers" =>'',
|
240
223
|
"Queues" =>'queues',
|
241
224
|
"Retries" =>'retries',
|
242
|
-
"Scheduled" =>'scheduled'
|
225
|
+
"Scheduled" =>'scheduled',
|
226
|
+
"Dashboard" =>'dashboard'
|
243
227
|
}
|
244
228
|
end
|
245
229
|
|