sidekiq 1.2.0 → 1.2.1
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/Changes.md +9 -0
- data/README.md +1 -1
- data/lib/sidekiq.rb +5 -0
- data/lib/sidekiq/cli.rb +11 -4
- data/lib/sidekiq/fetch.rb +13 -0
- data/lib/sidekiq/logging.rb +46 -0
- data/lib/sidekiq/manager.rb +1 -0
- data/lib/sidekiq/middleware/server/logging.rb +13 -9
- data/lib/sidekiq/processor.rb +3 -6
- data/lib/sidekiq/util.rb +2 -25
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +38 -6
- data/lib/sidekiq/worker.rb +4 -0
- data/myapp/app/workers/hard_worker.rb +1 -1
- data/test/helper.rb +1 -1
- data/test/test_cli.rb +3 -3
- data/test/test_stats.rb +2 -3
- data/test/test_web.rb +48 -8
- data/web/assets/javascripts/application.js +14 -3
- data/web/assets/stylesheets/application.css +4 -0
- data/web/views/index.slim +1 -19
- data/web/views/layout.slim +2 -0
- data/web/views/retries.slim +29 -0
- data/web/views/retry.slim +2 -2
- metadata +26 -24
data/Changes.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
1.2.1
|
2
|
+
-----------
|
3
|
+
|
4
|
+
- Sidekiq::Worker now has access to Sidekiq's standard logger
|
5
|
+
- Fix issue with non-StandardErrors leading to Processor exhaustion
|
6
|
+
- Fix issue with Fetcher slowing Sidekiq shutdown
|
7
|
+
- Print backtraces for all threads upon TTIN signal [#183]
|
8
|
+
- Overhaul retries Web UI with new index page and bulk operations [#184]
|
9
|
+
|
1
10
|
1.2.0
|
2
11
|
-----------
|
3
12
|
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ message format as Resque so it can integrate into an existing Resque processing
|
|
12
12
|
You can have Sidekiq and Resque run side-by-side at the same time and
|
13
13
|
use the Resque client to enqueue messages in Redis to be processed by Sidekiq.
|
14
14
|
|
15
|
-
At the same time, Sidekiq uses multithreading so it much more memory efficient than
|
15
|
+
At the same time, Sidekiq uses multithreading so it is much more memory efficient than
|
16
16
|
Resque (which forks a new process for every job). You'll find that you might need
|
17
17
|
50 200MB resque processes to peg your CPU whereas one 300MB Sidekiq process will peg
|
18
18
|
the same CPU and perform the same amount of work. Please see [my blog post on Resque's memory
|
data/lib/sidekiq.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'sidekiq/version'
|
2
|
+
require 'sidekiq/logging'
|
2
3
|
require 'sidekiq/client'
|
3
4
|
require 'sidekiq/worker'
|
4
5
|
require 'sidekiq/redis_connection'
|
@@ -90,4 +91,8 @@ module Sidekiq
|
|
90
91
|
MultiJson.encode(object)
|
91
92
|
end
|
92
93
|
|
94
|
+
def self.logger
|
95
|
+
Sidekiq::Logging.logger
|
96
|
+
end
|
97
|
+
|
93
98
|
end
|
data/lib/sidekiq/cli.rb
CHANGED
@@ -10,11 +10,18 @@ trap 'TERM' do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
trap 'USR1' do
|
13
|
-
Sidekiq
|
13
|
+
Sidekiq.logger.info "Received USR1, no longer accepting new work"
|
14
14
|
mgr = Sidekiq::CLI.instance.manager
|
15
15
|
mgr.stop! if mgr
|
16
16
|
end
|
17
17
|
|
18
|
+
trap 'TTIN' do
|
19
|
+
Thread.list.each do |thread|
|
20
|
+
puts "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
|
21
|
+
puts thread.backtrace.join("\n")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
18
25
|
require 'yaml'
|
19
26
|
require 'singleton'
|
20
27
|
require 'optparse'
|
@@ -40,13 +47,13 @@ module Sidekiq
|
|
40
47
|
|
41
48
|
def parse(args=ARGV)
|
42
49
|
@code = nil
|
43
|
-
Sidekiq
|
50
|
+
Sidekiq.logger
|
44
51
|
|
45
52
|
cli = parse_options(args)
|
46
53
|
config = parse_config(cli)
|
47
54
|
options.merge!(config.merge(cli))
|
48
55
|
|
49
|
-
Sidekiq
|
56
|
+
Sidekiq.logger.level = Logger::DEBUG if options[:verbose]
|
50
57
|
Celluloid.logger = nil
|
51
58
|
|
52
59
|
validate!
|
@@ -127,7 +134,7 @@ module Sidekiq
|
|
127
134
|
end
|
128
135
|
|
129
136
|
o.on "-v", "--verbose", "Print more verbose output" do
|
130
|
-
Sidekiq
|
137
|
+
Sidekiq.logger.level = ::Logger::DEBUG
|
131
138
|
end
|
132
139
|
|
133
140
|
o.on '-e', '--environment ENV', "Application environment" do |arg|
|
data/lib/sidekiq/fetch.rb
CHANGED
@@ -28,6 +28,8 @@ module Sidekiq
|
|
28
28
|
# a new fetch if the current fetch turned up nothing.
|
29
29
|
def fetch
|
30
30
|
watchdog('Fetcher#fetch died') do
|
31
|
+
return if Sidekiq::Fetcher.done?
|
32
|
+
|
31
33
|
begin
|
32
34
|
queue = nil
|
33
35
|
msg = nil
|
@@ -47,6 +49,17 @@ module Sidekiq
|
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
52
|
+
# Ugh. Say hello to a bloody hack.
|
53
|
+
# Can't find a clean way to get the fetcher to just stop processing
|
54
|
+
# its mailbox when shutdown starts.
|
55
|
+
def self.done!
|
56
|
+
@done = true
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.done?
|
60
|
+
@done
|
61
|
+
end
|
62
|
+
|
50
63
|
private
|
51
64
|
|
52
65
|
# Creating the Redis#blpop command takes into account any
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
module Sidekiq
|
5
|
+
module Logging
|
6
|
+
|
7
|
+
class Pretty < Logger::Formatter
|
8
|
+
# Provide a call() method that returns the formatted message.
|
9
|
+
def call(severity, time, program_name, message)
|
10
|
+
"#{time.utc.iso8601} #{Process.pid} TID-#{Thread.current.object_id.to_s(36)}#{context} #{severity}: #{message}\n"
|
11
|
+
end
|
12
|
+
|
13
|
+
def context
|
14
|
+
c = Thread.current[:sidekiq_context]
|
15
|
+
c ? " #{c}" : ''
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.with_context(msg)
|
20
|
+
begin
|
21
|
+
Thread.current[:sidekiq_context] = msg
|
22
|
+
yield
|
23
|
+
ensure
|
24
|
+
Thread.current[:sidekiq_context] = nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.logger
|
29
|
+
@logger ||= begin
|
30
|
+
log = Logger.new(STDOUT)
|
31
|
+
log.level = Logger::INFO
|
32
|
+
log.formatter = Pretty.new
|
33
|
+
log
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.logger=(log)
|
38
|
+
@logger = (log ? log : Logger.new('/dev/null'))
|
39
|
+
end
|
40
|
+
|
41
|
+
def logger
|
42
|
+
Sidekiq::Logging.logger
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
data/lib/sidekiq/manager.rb
CHANGED
@@ -2,15 +2,19 @@ module Sidekiq
|
|
2
2
|
module Middleware
|
3
3
|
module Server
|
4
4
|
class Logging
|
5
|
+
|
5
6
|
def call(*args)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
Sidekiq::Logging.with_context("#{args[0].class.to_s} MSG-#{args[0].object_id.to_s(36)}") do
|
8
|
+
begin
|
9
|
+
start = Time.now
|
10
|
+
logger.info { "start" }
|
11
|
+
yield
|
12
|
+
logger.info { "done: #{elapsed(start)} sec" }
|
13
|
+
rescue
|
14
|
+
logger.info { "fail: #{elapsed(start)} sec" }
|
15
|
+
raise
|
16
|
+
end
|
17
|
+
end
|
14
18
|
end
|
15
19
|
|
16
20
|
def elapsed(start)
|
@@ -18,7 +22,7 @@ module Sidekiq
|
|
18
22
|
end
|
19
23
|
|
20
24
|
def logger
|
21
|
-
Sidekiq
|
25
|
+
Sidekiq.logger
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
data/lib/sidekiq/processor.rb
CHANGED
@@ -55,22 +55,20 @@ module Sidekiq
|
|
55
55
|
redis do |conn|
|
56
56
|
conn.multi do
|
57
57
|
conn.sadd('workers', self)
|
58
|
-
conn.setex("worker:#{self}:started",
|
58
|
+
conn.setex("worker:#{self}:started", EXPIRY, Time.now.to_s)
|
59
59
|
hash = {:queue => queue, :payload => msg, :run_at => Time.now.strftime("%Y/%m/%d %H:%M:%S %Z")}
|
60
|
-
conn.setex("worker:#{self}",
|
60
|
+
conn.setex("worker:#{self}", EXPIRY, Sidekiq.dump_json(hash))
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
64
|
dying = false
|
65
65
|
begin
|
66
66
|
yield
|
67
|
-
rescue
|
67
|
+
rescue Exception
|
68
68
|
dying = true
|
69
|
-
# Uh oh, error. We will die so unregister as much as we can first.
|
70
69
|
redis do |conn|
|
71
70
|
conn.multi do
|
72
71
|
conn.incrby("stat:failed", 1)
|
73
|
-
conn.del("stat:processed:#{self}")
|
74
72
|
end
|
75
73
|
end
|
76
74
|
raise
|
@@ -81,7 +79,6 @@ module Sidekiq
|
|
81
79
|
conn.del("worker:#{self}")
|
82
80
|
conn.del("worker:#{self}:started")
|
83
81
|
conn.incrby("stat:processed", 1)
|
84
|
-
conn.incrby("stat:processed:#{self}", 1) unless dying
|
85
82
|
end
|
86
83
|
end
|
87
84
|
end
|
data/lib/sidekiq/util.rb
CHANGED
@@ -1,33 +1,10 @@
|
|
1
|
-
require 'time'
|
2
|
-
require 'logger'
|
3
|
-
|
4
1
|
module Sidekiq
|
5
2
|
##
|
6
3
|
# This module is part of Sidekiq core and not intended for extensions.
|
7
4
|
#
|
8
5
|
module Util
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
class Pretty < Logger::Formatter
|
13
|
-
# Provide a call() method that returns the formatted message.
|
14
|
-
def call(severity, time, program_name, message)
|
15
|
-
"#{time.utc.iso8601} #{Process.pid} TID-#{Thread.current.object_id.to_s(36)} #{severity}: #{message}\n"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.logger
|
20
|
-
@logger ||= begin
|
21
|
-
log = Logger.new(STDOUT)
|
22
|
-
log.level = Logger::INFO
|
23
|
-
log.formatter = Pretty.new
|
24
|
-
log
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.logger=(log)
|
29
|
-
@logger = (log ? log : Logger.new('/dev/null'))
|
30
|
-
end
|
7
|
+
EXPIRY = 60 * 60
|
31
8
|
|
32
9
|
def constantize(camel_cased_word)
|
33
10
|
names = camel_cased_word.split('::')
|
@@ -49,7 +26,7 @@ module Sidekiq
|
|
49
26
|
end
|
50
27
|
|
51
28
|
def logger
|
52
|
-
Sidekiq
|
29
|
+
Sidekiq.logger
|
53
30
|
end
|
54
31
|
|
55
32
|
def redis(&block)
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web.rb
CHANGED
@@ -61,15 +61,15 @@ module Sidekiq
|
|
61
61
|
Sidekiq.redis { |conn| conn.zcard('retry') }
|
62
62
|
end
|
63
63
|
|
64
|
-
def retries
|
64
|
+
def retries(count=50)
|
65
65
|
Sidekiq.redis do |conn|
|
66
|
-
results = conn.zrange('retry', 0,
|
66
|
+
results = conn.zrange('retry', 0, count, :withscores => true)
|
67
67
|
results.each_slice(2).map { |msg, score| [Sidekiq.load_json(msg), Float(score)] }
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
71
|
def queues
|
72
|
-
Sidekiq.redis do |conn|
|
72
|
+
@queues ||= Sidekiq.redis do |conn|
|
73
73
|
conn.smembers('queues').map do |q|
|
74
74
|
[q, conn.llen("queue:#{q}") || 0]
|
75
75
|
end.sort { |x,y| x[1] <=> y[1] }
|
@@ -99,6 +99,10 @@ module Sidekiq
|
|
99
99
|
def relative_time(time)
|
100
100
|
%{<time datetime="#{time.getutc.iso8601}">#{time}</time>}
|
101
101
|
end
|
102
|
+
|
103
|
+
def display_args(args, count=100)
|
104
|
+
args.map { |arg| a = arg.inspect; a.size > count ? "#{a[0..count]}..." : a }.join(", ")
|
105
|
+
end
|
102
106
|
end
|
103
107
|
|
104
108
|
get "/" do
|
@@ -125,14 +129,42 @@ module Sidekiq
|
|
125
129
|
halt 404 unless params[:score]
|
126
130
|
@score = params[:score].to_f
|
127
131
|
@retries = retries_with_score(@score)
|
128
|
-
redirect root_path if @retries.empty?
|
132
|
+
redirect "#{root_path}retries" if @retries.empty?
|
129
133
|
slim :retry
|
130
134
|
end
|
131
135
|
|
136
|
+
get '/retries' do
|
137
|
+
@retries = retries
|
138
|
+
slim :retries
|
139
|
+
end
|
140
|
+
|
141
|
+
post '/retries' do
|
142
|
+
halt 404 unless params[:score]
|
143
|
+
params[:score].each do |score|
|
144
|
+
s = score.to_f
|
145
|
+
if params['retry']
|
146
|
+
process_score(s, :retry)
|
147
|
+
elsif params['delete']
|
148
|
+
process_score(s, :delete)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
redirect root_path
|
152
|
+
end
|
153
|
+
|
132
154
|
post "/retries/:score" do
|
133
155
|
halt 404 unless params[:score]
|
134
156
|
score = params[:score].to_f
|
135
157
|
if params['retry']
|
158
|
+
process_score(score, :retry)
|
159
|
+
elsif params['delete']
|
160
|
+
process_score(score, :delete)
|
161
|
+
end
|
162
|
+
redirect root_path
|
163
|
+
end
|
164
|
+
|
165
|
+
def process_score(score, operation)
|
166
|
+
case operation
|
167
|
+
when :retry
|
136
168
|
Sidekiq.redis do |conn|
|
137
169
|
results = conn.zrangebyscore('retry', score, score)
|
138
170
|
conn.zremrangebyscore('retry', score, score)
|
@@ -141,13 +173,13 @@ module Sidekiq
|
|
141
173
|
conn.rpush("queue:#{msg['queue']}", message)
|
142
174
|
end
|
143
175
|
end
|
144
|
-
|
176
|
+
when :delete
|
145
177
|
Sidekiq.redis do |conn|
|
146
178
|
conn.zremrangebyscore('retry', score, score)
|
147
179
|
end
|
148
180
|
end
|
149
|
-
redirect root_path
|
150
181
|
end
|
182
|
+
|
151
183
|
end
|
152
184
|
|
153
185
|
end
|
data/lib/sidekiq/worker.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -10,7 +10,7 @@ require 'minitest/autorun'
|
|
10
10
|
|
11
11
|
require 'sidekiq'
|
12
12
|
require 'sidekiq/util'
|
13
|
-
Sidekiq
|
13
|
+
Sidekiq.logger.level = Logger::ERROR
|
14
14
|
|
15
15
|
require 'sidekiq/redis_connection'
|
16
16
|
REDIS = Sidekiq::RedisConnection.create(:url => "redis://localhost/15", :namespace => 'testy')
|
data/test/test_cli.rb
CHANGED
@@ -51,11 +51,11 @@ class TestCli < MiniTest::Unit::TestCase
|
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'sets verbose' do
|
54
|
-
old = Sidekiq
|
54
|
+
old = Sidekiq.logger.level
|
55
55
|
@cli.parse(['sidekiq', '-v', '-r', './test/fake_env.rb'])
|
56
|
-
assert_equal Logger::DEBUG, Sidekiq
|
56
|
+
assert_equal Logger::DEBUG, Sidekiq.logger.level
|
57
57
|
# If we leave the logger at DEBUG it'll add a lot of noise to the test output
|
58
|
-
Sidekiq
|
58
|
+
Sidekiq.logger.level = old
|
59
59
|
end
|
60
60
|
|
61
61
|
describe 'with pidfile' do
|
data/test/test_stats.rb
CHANGED
@@ -28,10 +28,11 @@ class TestStats < MiniTest::Unit::TestCase
|
|
28
28
|
|
29
29
|
processor = Sidekiq::Processor.new(boss)
|
30
30
|
boss.expect(:processor_done!, nil, [processor])
|
31
|
+
boss.expect(:processor_done!, nil, [processor])
|
32
|
+
boss.expect(:processor_done!, nil, [processor])
|
31
33
|
|
32
34
|
assert_equal 0, conn.get('stat:failed').to_i
|
33
35
|
assert_equal 0, conn.get('stat:processed').to_i
|
34
|
-
assert_equal 0, conn.get("stat:processed:#{processor}").to_i
|
35
36
|
|
36
37
|
processor.process(msg, 'xyzzy')
|
37
38
|
processor.process(msg, 'xyzzy')
|
@@ -39,7 +40,6 @@ class TestStats < MiniTest::Unit::TestCase
|
|
39
40
|
|
40
41
|
assert_equal 0, conn.get('stat:failed').to_i
|
41
42
|
assert_equal 3, conn.get('stat:processed').to_i
|
42
|
-
assert_equal 3, conn.get("stat:processed:#{processor}").to_i
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -61,7 +61,6 @@ class TestStats < MiniTest::Unit::TestCase
|
|
61
61
|
|
62
62
|
assert_equal 1, conn.get('stat:failed').to_i
|
63
63
|
assert_equal 1, conn.get('stat:processed').to_i
|
64
|
-
assert_equal nil, conn.get("stat:processed:#{pstr}")
|
65
64
|
end
|
66
65
|
end
|
67
66
|
|
data/test/test_web.rb
CHANGED
@@ -27,24 +27,25 @@ class TestWeb < MiniTest::Unit::TestCase
|
|
27
27
|
it 'shows active queues' do
|
28
28
|
get '/'
|
29
29
|
assert_equal 200, last_response.status
|
30
|
-
assert_match
|
31
|
-
refute_match last_response.body
|
30
|
+
assert_match /Sidekiq is idle/, last_response.body
|
31
|
+
refute_match /default/, last_response.body
|
32
32
|
|
33
33
|
assert WebWorker.perform_async(1, 2)
|
34
34
|
|
35
35
|
get '/'
|
36
36
|
assert_equal 200, last_response.status
|
37
|
-
assert_match
|
38
|
-
assert_match last_response.body
|
39
|
-
refute_match last_response.body
|
37
|
+
assert_match /Sidekiq is idle/, last_response.body
|
38
|
+
assert_match /default/, last_response.body
|
39
|
+
refute_match /foo/, last_response.body
|
40
40
|
|
41
41
|
assert Sidekiq::Client.push('queue' => :foo, 'class' => WebWorker, 'args' => [1, 3])
|
42
42
|
|
43
43
|
get '/'
|
44
44
|
assert_equal 200, last_response.status
|
45
|
-
assert_match
|
46
|
-
assert_match last_response.body
|
47
|
-
assert_match last_response.body
|
45
|
+
assert_match /Sidekiq is idle/, last_response.body
|
46
|
+
assert_match /default/, last_response.body
|
47
|
+
assert_match /foo/, last_response.body
|
48
|
+
assert_match /Backlog: 2/, last_response.body
|
48
49
|
end
|
49
50
|
|
50
51
|
it 'handles queues with no name' do
|
@@ -78,5 +79,44 @@ class TestWeb < MiniTest::Unit::TestCase
|
|
78
79
|
refute conn.smembers('queues').include?('foo')
|
79
80
|
end
|
80
81
|
end
|
82
|
+
|
83
|
+
it 'can display retries' do
|
84
|
+
get '/retries'
|
85
|
+
assert_equal 200, last_response.status
|
86
|
+
assert_match /found/, last_response.body
|
87
|
+
refute_match /HardWorker/, last_response.body
|
88
|
+
|
89
|
+
add_retry
|
90
|
+
|
91
|
+
get '/retries'
|
92
|
+
assert_equal 200, last_response.status
|
93
|
+
refute_match /found/, last_response.body
|
94
|
+
assert_match /HardWorker/, last_response.body
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'can display a single retry' do
|
98
|
+
get '/retries/12938712.123333'
|
99
|
+
assert_equal 302, last_response.status
|
100
|
+
_, score = add_retry
|
101
|
+
|
102
|
+
get "/retries/#{score}"
|
103
|
+
assert_equal 200, last_response.status
|
104
|
+
assert_match /HardWorker/, last_response.body
|
105
|
+
end
|
106
|
+
|
107
|
+
def add_retry
|
108
|
+
msg = { 'class' => 'HardWorker',
|
109
|
+
'args' => ['bob', 1, Time.now.to_f],
|
110
|
+
'queue' => 'default',
|
111
|
+
'error_message' => 'Some fake message',
|
112
|
+
'error_class' => 'RuntimeError',
|
113
|
+
'retry_count' => 0,
|
114
|
+
'failed_at' => Time.now.utc, }
|
115
|
+
score = Time.now.to_f
|
116
|
+
Sidekiq.redis do |conn|
|
117
|
+
conn.zadd('retry', score, Sidekiq.dump_json(msg))
|
118
|
+
end
|
119
|
+
[msg, score]
|
120
|
+
end
|
81
121
|
end
|
82
122
|
end
|
@@ -3,7 +3,18 @@
|
|
3
3
|
//= require bootstrap
|
4
4
|
//= require_tree .
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
$(function() {
|
7
|
+
$.timeago.settings.allowFuture = true
|
8
|
+
$("time").timeago();
|
9
|
+
});
|
10
|
+
|
11
|
+
$(function() {
|
12
|
+
$('.check_all').live('click', function() {
|
13
|
+
var checked = $(this).attr('checked');
|
14
|
+
if (checked == 'checked') {
|
15
|
+
$('input[type=checkbox]', $(this).closest('table')).attr('checked', checked);
|
16
|
+
} else {
|
17
|
+
$('input[type=checkbox]', $(this).closest('table')).removeAttr('checked');
|
18
|
+
}
|
19
|
+
});
|
9
20
|
});
|
data/web/views/index.slim
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
p Failed: #{failed}
|
6
6
|
p Busy Workers: #{workers.size}
|
7
7
|
p Retries Pending: #{retry_count}
|
8
|
+
p Queue Backlog: #{queues.map{|q,size| size}.sum}
|
8
9
|
|
9
10
|
.tabbable
|
10
11
|
ul.nav.nav-tabs
|
@@ -12,8 +13,6 @@
|
|
12
13
|
a href="#workers" data-toggle="tab" Busy Workers
|
13
14
|
li
|
14
15
|
a href="#queues" data-toggle="tab" Queues
|
15
|
-
li
|
16
|
-
a href="#retries" data-toggle="tab" Retries
|
17
16
|
.tab-content
|
18
17
|
#workers.tab-pane.active
|
19
18
|
table class="table table-striped table-bordered"
|
@@ -46,21 +45,4 @@
|
|
46
45
|
form action="#{root_path}queues/#{queue}" method="post"
|
47
46
|
input.btn.btn-danger type="submit" name="delete" value="Delete"
|
48
47
|
|
49
|
-
#retries.tab-pane
|
50
|
-
table class="table table-striped table-bordered"
|
51
|
-
tr
|
52
|
-
th Next Retry
|
53
|
-
th Retry Count
|
54
|
-
th Queue
|
55
|
-
th Worker
|
56
|
-
th Args
|
57
|
-
- retries.each do |(msg, score)|
|
58
|
-
tr
|
59
|
-
td
|
60
|
-
a href="retries/#{score}"== relative_time(Time.at(score))
|
61
|
-
td= msg['retry_count']
|
62
|
-
td
|
63
|
-
a href="queues/#{msg['queue']}" #{msg['queue']}
|
64
|
-
td= msg['class']
|
65
|
-
td= msg['args'].inspect[0..100]
|
66
48
|
|
data/web/views/layout.slim
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
h1 Retries
|
2
|
+
|
3
|
+
- if @retries.size > 0
|
4
|
+
form action="#{root_path}retries" method="post"
|
5
|
+
table class="table table-striped table-bordered"
|
6
|
+
tr
|
7
|
+
th
|
8
|
+
input type="checkbox" class="check_all"
|
9
|
+
th Next Retry
|
10
|
+
th Retry Count
|
11
|
+
th Queue
|
12
|
+
th Worker
|
13
|
+
th Args
|
14
|
+
- @retries.each do |(msg, score)|
|
15
|
+
tr
|
16
|
+
td
|
17
|
+
input type='checkbox' name='score[]' value='#{score}'
|
18
|
+
td
|
19
|
+
a href="#{root_path}retries/#{score}"== relative_time(Time.at(score))
|
20
|
+
td= msg['retry_count']
|
21
|
+
td
|
22
|
+
a href="#{root_path}queues/#{msg['queue']}" #{msg['queue']}
|
23
|
+
td= msg['class']
|
24
|
+
td= display_args(msg['args'])
|
25
|
+
input.btn.btn-primary type="submit" name="retry" value="Retry Now"
|
26
|
+
input.btn.btn-danger type="submit" name="delete" value="Delete"
|
27
|
+
- else
|
28
|
+
p No retries found.
|
29
|
+
a href="#{root_path}" Back
|
data/web/views/retry.slim
CHANGED
@@ -15,7 +15,7 @@ header
|
|
15
15
|
tr
|
16
16
|
th Job Arguments
|
17
17
|
td
|
18
|
-
code= msg['args']
|
18
|
+
code= display_args(msg['args'], 1000)
|
19
19
|
- if msg['retry_count'] > 0
|
20
20
|
tr
|
21
21
|
th Retry Count
|
@@ -47,6 +47,6 @@ header
|
|
47
47
|
td
|
48
48
|
code== msg['error_backtrace'].join("<br/>")
|
49
49
|
form.form-horizontal action="#{root_path}retries/#{@score}" method="post"
|
50
|
-
a.btn href="#{root_path}" ← Back
|
50
|
+
a.btn href="#{root_path}retries" ← Back
|
51
51
|
input.btn.btn-primary type="submit" name="retry" value="Retry Now"
|
52
52
|
input.btn.btn-danger type="submit" name="delete" value="Delete"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
16
|
-
requirement: &
|
16
|
+
requirement: &70113151847120 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70113151847120
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: redis-namespace
|
27
|
-
requirement: &
|
27
|
+
requirement: &70113151845720 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70113151845720
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: connection_pool
|
38
|
-
requirement: &
|
38
|
+
requirement: &70113151844280 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 0.9.0
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70113151844280
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: celluloid
|
49
|
-
requirement: &
|
49
|
+
requirement: &70113151842720 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 0.10.0
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70113151842720
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: multi_json
|
60
|
-
requirement: &
|
60
|
+
requirement: &70113151841480 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '1'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70113151841480
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: minitest
|
71
|
-
requirement: &
|
71
|
+
requirement: &70113151840480 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70113151840480
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: sinatra
|
82
|
-
requirement: &
|
82
|
+
requirement: &70113151839320 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70113151839320
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: slim
|
93
|
-
requirement: &
|
93
|
+
requirement: &70113151838740 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70113151838740
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: rake
|
104
|
-
requirement: &
|
104
|
+
requirement: &70113151837560 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70113151837560
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: actionmailer
|
115
|
-
requirement: &
|
115
|
+
requirement: &70113151833660 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ~>
|
@@ -120,10 +120,10 @@ dependencies:
|
|
120
120
|
version: '3'
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *70113151833660
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: activerecord
|
126
|
-
requirement: &
|
126
|
+
requirement: &70113151829900 !ruby/object:Gem::Requirement
|
127
127
|
none: false
|
128
128
|
requirements:
|
129
129
|
- - ~>
|
@@ -131,7 +131,7 @@ dependencies:
|
|
131
131
|
version: '3'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
|
-
version_requirements: *
|
134
|
+
version_requirements: *70113151829900
|
135
135
|
description: Simple, efficient message processing for Ruby
|
136
136
|
email:
|
137
137
|
- mperham@gmail.com
|
@@ -173,6 +173,7 @@ files:
|
|
173
173
|
- lib/sidekiq/extensions/active_record.rb
|
174
174
|
- lib/sidekiq/extensions/generic_proxy.rb
|
175
175
|
- lib/sidekiq/fetch.rb
|
176
|
+
- lib/sidekiq/logging.rb
|
176
177
|
- lib/sidekiq/manager.rb
|
177
178
|
- lib/sidekiq/middleware/chain.rb
|
178
179
|
- lib/sidekiq/middleware/client/unique_jobs.rb
|
@@ -272,6 +273,7 @@ files:
|
|
272
273
|
- web/views/index.slim
|
273
274
|
- web/views/layout.slim
|
274
275
|
- web/views/queue.slim
|
276
|
+
- web/views/retries.slim
|
275
277
|
- web/views/retry.slim
|
276
278
|
homepage: http://mperham.github.com/sidekiq
|
277
279
|
licenses: []
|