sidekiq 2.6.0 → 2.6.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 +7 -0
- data/README.md +1 -1
- data/lib/sidekiq.rb +12 -1
- data/lib/sidekiq/api.rb +8 -0
- data/lib/sidekiq/capistrano.rb +0 -1
- data/lib/sidekiq/core_ext.rb +9 -2
- data/lib/sidekiq/middleware/chain.rb +30 -0
- data/lib/sidekiq/processor.rb +2 -4
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +8 -10
- data/sidekiq.gemspec +1 -1
- data/test/test_middleware.rb +29 -1
- data/test/test_web.rb +4 -1
- data/web/assets/javascripts/dashboard.js +20 -0
- data/web/views/_summary.slim +7 -7
- data/web/views/dashboard.slim +24 -19
- metadata +4 -5
- data/lib/sidekiq/stats.rb +0 -13
data/Changes.md
CHANGED
data/README.md
CHANGED
@@ -54,7 +54,7 @@ Please see the [sidekiq wiki](https://github.com/mperham/sidekiq/wiki) for more
|
|
54
54
|
but bug reports or feature requests suggestions should still go through [issues on Github](https://github.com/mperham/sidekiq/issues).
|
55
55
|
|
56
56
|
There's also a mailing list via [Librelist](http://librelist.org) that you can subscribe to by sending
|
57
|
-
|
57
|
+
an email to <sidekiq@librelist.org> with a greeting in the body. To unsubscribe, send an email to <sidekiq-unsubscribe@librelist.org> and that's it!
|
58
58
|
Once archiving begins, you'll be able to visit [the archives](http://librelist.com/browser/sidekiq/) to see past threads.
|
59
59
|
|
60
60
|
|
data/lib/sidekiq.rb
CHANGED
@@ -4,7 +4,6 @@ require 'sidekiq/client'
|
|
4
4
|
require 'sidekiq/worker'
|
5
5
|
require 'sidekiq/redis_connection'
|
6
6
|
require 'sidekiq/util'
|
7
|
-
require 'sidekiq/stats'
|
8
7
|
require 'sidekiq/api'
|
9
8
|
|
10
9
|
require 'sidekiq/extensions/class_methods'
|
@@ -109,4 +108,16 @@ module Sidekiq
|
|
109
108
|
self.options[:poll_interval] = interval
|
110
109
|
end
|
111
110
|
|
111
|
+
##
|
112
|
+
# deprecated
|
113
|
+
def self.size(*queues)
|
114
|
+
return Sidekiq::Stats.new.enqueued if queues.empty?
|
115
|
+
|
116
|
+
Sidekiq.redis { |conn|
|
117
|
+
conn.multi {
|
118
|
+
queues.map { |q| conn.llen("queue:#{q}") }
|
119
|
+
}
|
120
|
+
}.inject(0) { |memo, count| memo += count }
|
121
|
+
end
|
122
|
+
|
112
123
|
end
|
data/lib/sidekiq/api.rb
CHANGED
@@ -33,6 +33,14 @@ module Sidekiq
|
|
33
33
|
queues.values.inject(&:+) || 0
|
34
34
|
end
|
35
35
|
|
36
|
+
def scheduled_size
|
37
|
+
Sidekiq.redis {|c| c.zcard('schedule') }
|
38
|
+
end
|
39
|
+
|
40
|
+
def retry_size
|
41
|
+
Sidekiq.redis {|c| c.zcard('retry') }
|
42
|
+
end
|
43
|
+
|
36
44
|
class History
|
37
45
|
def initialize(days_previous, start_date = nil)
|
38
46
|
@days_previous = days_previous
|
data/lib/sidekiq/capistrano.rb
CHANGED
@@ -2,7 +2,6 @@ Capistrano::Configuration.instance.load do
|
|
2
2
|
before "deploy:update_code", "sidekiq:quiet"
|
3
3
|
after "deploy:stop", "sidekiq:stop"
|
4
4
|
after "deploy:start", "sidekiq:start"
|
5
|
-
after "deploy:restart", "sidekiq:restart"
|
6
5
|
|
7
6
|
_cset(:sidekiq_cmd) { "#{fetch(:bundle_cmd, "bundle")} exec sidekiq" }
|
8
7
|
_cset(:sidekiqctl_cmd) { "#{fetch(:bundle_cmd, "bundle")} exec sidekiqctl" }
|
data/lib/sidekiq/core_ext.rb
CHANGED
@@ -60,8 +60,15 @@ rescue LoadError
|
|
60
60
|
self[key.to_s] = delete(key)
|
61
61
|
end
|
62
62
|
self
|
63
|
-
end
|
64
|
-
|
63
|
+
end if !{}.respond_to?(:stringify_keys)
|
64
|
+
|
65
|
+
def symbolize_keys
|
66
|
+
keys.each do |key|
|
67
|
+
self[(key.to_sym rescue key) || key] = delete(key)
|
68
|
+
end
|
69
|
+
self
|
70
|
+
end if !{}.respond_to?(:symbolize_keys)
|
71
|
+
end
|
65
72
|
end
|
66
73
|
|
67
74
|
begin
|
@@ -23,6 +23,22 @@ module Sidekiq
|
|
23
23
|
# end
|
24
24
|
# end
|
25
25
|
#
|
26
|
+
# To insert immediately preceding another entry:
|
27
|
+
#
|
28
|
+
# Sidekiq.configure_client do |config|
|
29
|
+
# config.client_middleware do |chain|
|
30
|
+
# chain.insert_before ActiveRecord, MyClientHook
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# To insert immediately after another entry:
|
35
|
+
#
|
36
|
+
# Sidekiq.configure_client do |config|
|
37
|
+
# config.client_middleware do |chain|
|
38
|
+
# chain.insert_after ActiveRecord, MyClientHook
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
#
|
26
42
|
# This is an example of a minimal server middleware:
|
27
43
|
#
|
28
44
|
# class MyServerHook
|
@@ -60,6 +76,20 @@ module Sidekiq
|
|
60
76
|
entries << Entry.new(klass, *args) unless exists?(klass)
|
61
77
|
end
|
62
78
|
|
79
|
+
def insert_before(oldklass, newklass, *args)
|
80
|
+
i = entries.index { |entry| entry.klass == newklass }
|
81
|
+
new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
|
82
|
+
i = entries.find_index { |entry| entry.klass == oldklass } || 0
|
83
|
+
entries.insert(i, new_entry)
|
84
|
+
end
|
85
|
+
|
86
|
+
def insert_after(oldklass, newklass, *args)
|
87
|
+
i = entries.index { |entry| entry.klass == newklass }
|
88
|
+
new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
|
89
|
+
i = entries.find_index { |entry| entry.klass == oldklass } || entries.count - 1
|
90
|
+
entries.insert(i+1, new_entry)
|
91
|
+
end
|
92
|
+
|
63
93
|
def exists?(klass)
|
64
94
|
entries.any? { |entry| entry.klass == klass }
|
65
95
|
end
|
data/lib/sidekiq/processor.rb
CHANGED
@@ -43,8 +43,8 @@ module Sidekiq
|
|
43
43
|
worker.perform(*cloned(msg['args']))
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
47
|
-
|
46
|
+
rescue Exception => ex
|
47
|
+
handle_exception(ex, msg || { :message => msgstr })
|
48
48
|
raise
|
49
49
|
end
|
50
50
|
end
|
@@ -72,11 +72,9 @@ module Sidekiq
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
-
dying = false
|
76
75
|
begin
|
77
76
|
yield
|
78
77
|
rescue Exception
|
79
|
-
dying = true
|
80
78
|
redis do |conn|
|
81
79
|
conn.multi do
|
82
80
|
conn.incrby("stat:failed", 1)
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web.rb
CHANGED
@@ -38,14 +38,6 @@ module Sidekiq
|
|
38
38
|
@stats ||= Sidekiq::Stats.new
|
39
39
|
end
|
40
40
|
|
41
|
-
def scheduled_job_count
|
42
|
-
Sidekiq::ScheduledSet.new.size
|
43
|
-
end
|
44
|
-
|
45
|
-
def retry_job_count
|
46
|
-
Sidekiq::RetrySet.new.size
|
47
|
-
end
|
48
|
-
|
49
41
|
def retries_with_score(score)
|
50
42
|
Sidekiq.redis do |conn|
|
51
43
|
results = conn.zrangebyscore('retry', score, score)
|
@@ -204,7 +196,7 @@ module Sidekiq
|
|
204
196
|
end
|
205
197
|
|
206
198
|
get '/dashboard' do
|
207
|
-
@redis_info = Sidekiq.redis{ |conn| conn.info }
|
199
|
+
@redis_info = Sidekiq.redis { |conn| conn.info }
|
208
200
|
stats_history = Sidekiq::Stats::History.new((params[:days] || 30).to_i)
|
209
201
|
@processed_history = stats_history.processed
|
210
202
|
@failed_history = stats_history.failed
|
@@ -214,7 +206,13 @@ module Sidekiq
|
|
214
206
|
get '/dashboard/stats' do
|
215
207
|
stats = Sidekiq::Stats.new
|
216
208
|
content_type :json
|
217
|
-
Sidekiq.dump_json({
|
209
|
+
Sidekiq.dump_json({
|
210
|
+
processed: stats.processed,
|
211
|
+
failed: stats.failed,
|
212
|
+
enqueued: stats.enqueued,
|
213
|
+
scheduled: stats.scheduled_size,
|
214
|
+
retries: stats.retry_size,
|
215
|
+
})
|
218
216
|
end
|
219
217
|
|
220
218
|
def self.tabs
|
data/sidekiq.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = Sidekiq::VERSION
|
17
17
|
gem.add_dependency 'redis', '~> 3'
|
18
18
|
gem.add_dependency 'redis-namespace'
|
19
|
-
gem.add_dependency 'connection_pool', '~> 0
|
19
|
+
gem.add_dependency 'connection_pool', '~> 1.0'
|
20
20
|
gem.add_dependency 'celluloid', '~> 0.12.0'
|
21
21
|
gem.add_dependency 'multi_json', '~> 1'
|
22
22
|
gem.add_development_dependency 'minitest', '~> 4'
|
data/test/test_middleware.rb
CHANGED
@@ -41,6 +41,32 @@ class TestMiddleware < MiniTest::Unit::TestCase
|
|
41
41
|
def call(*args)
|
42
42
|
end
|
43
43
|
end
|
44
|
+
|
45
|
+
class AnotherCustomMiddleware
|
46
|
+
def initialize(name, recorder)
|
47
|
+
@name = name
|
48
|
+
@recorder = recorder
|
49
|
+
end
|
50
|
+
|
51
|
+
def call(*args)
|
52
|
+
@recorder << [@name, 'before']
|
53
|
+
yield
|
54
|
+
@recorder << [@name, 'after']
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class YetAnotherCustomMiddleware
|
59
|
+
def initialize(name, recorder)
|
60
|
+
@name = name
|
61
|
+
@recorder = recorder
|
62
|
+
end
|
63
|
+
|
64
|
+
def call(*args)
|
65
|
+
@recorder << [@name, 'before']
|
66
|
+
yield
|
67
|
+
@recorder << [@name, 'after']
|
68
|
+
end
|
69
|
+
end
|
44
70
|
|
45
71
|
it 'executes middleware in the proper order' do
|
46
72
|
msg = Sidekiq.dump_json({ 'class' => CustomWorker.to_s, 'args' => [$recorder] })
|
@@ -48,6 +74,8 @@ class TestMiddleware < MiniTest::Unit::TestCase
|
|
48
74
|
Sidekiq.server_middleware do |chain|
|
49
75
|
# should only add once, second should be ignored
|
50
76
|
2.times { |i| chain.add CustomMiddleware, i.to_s, $recorder }
|
77
|
+
chain.insert_before CustomMiddleware, AnotherCustomMiddleware, '2', $recorder
|
78
|
+
chain.insert_after AnotherCustomMiddleware, YetAnotherCustomMiddleware, '3', $recorder
|
51
79
|
end
|
52
80
|
|
53
81
|
boss = MiniTest::Mock.new
|
@@ -56,7 +84,7 @@ class TestMiddleware < MiniTest::Unit::TestCase
|
|
56
84
|
actor.expect(:processor_done, nil, [processor])
|
57
85
|
boss.expect(:async, actor, [])
|
58
86
|
processor.process(msg, 'default')
|
59
|
-
assert_equal %w(0 before work_performed 0 after), $recorder.flatten
|
87
|
+
assert_equal %w(2 before 3 before 0 before work_performed 0 after 3 after 2 after), $recorder.flatten
|
60
88
|
end
|
61
89
|
|
62
90
|
it 'allows middleware to abruptly stop processing rest of chain' do
|
data/test/test_web.rb
CHANGED
@@ -205,9 +205,12 @@ class TestWeb < MiniTest::Unit::TestCase
|
|
205
205
|
conn.set("stat:processed", 5)
|
206
206
|
conn.set("stat:failed", 2)
|
207
207
|
end
|
208
|
+
2.times { add_retry }
|
209
|
+
3.times { add_scheduled }
|
210
|
+
|
208
211
|
get '/dashboard/stats'
|
209
212
|
assert_equal 200, last_response.status
|
210
|
-
assert_equal "{\"processed\":5,\"failed\":2}", last_response.body
|
213
|
+
assert_equal "{\"processed\":5,\"failed\":2,\"enqueued\":0,\"scheduled\":3,\"retries\":2}", last_response.body
|
211
214
|
end
|
212
215
|
|
213
216
|
def add_scheduled
|
@@ -52,6 +52,8 @@ var realtimeGraph = function(updatePath) {
|
|
52
52
|
|
53
53
|
Sidekiq.processed = data.processed;
|
54
54
|
Sidekiq.failed = data.failed;
|
55
|
+
|
56
|
+
updateStatsSummary(data);
|
55
57
|
});
|
56
58
|
i++;
|
57
59
|
}, timeInterval);
|
@@ -104,6 +106,24 @@ var createSeries = function(obj) {
|
|
104
106
|
return series;
|
105
107
|
};
|
106
108
|
|
109
|
+
var updateStatsSummary = function(data) {
|
110
|
+
$('ul.summary li.processed span.count').html(data.processed.numberWithDelimiter())
|
111
|
+
$('ul.summary li.failed span.count').html(data.failed.numberWithDelimiter())
|
112
|
+
$('ul.summary li.scheduled span.count').html(data.scheduled.numberWithDelimiter())
|
113
|
+
$('ul.summary li.retries span.count').html(data.retries.numberWithDelimiter())
|
114
|
+
$('ul.summary li.enqueued span.count').html(data.enqueued.numberWithDelimiter())
|
115
|
+
}
|
116
|
+
|
117
|
+
Number.prototype.numberWithDelimiter = function(delimiter) {
|
118
|
+
var number = this + '', delimiter = delimiter || ',';
|
119
|
+
var split = number.split('.');
|
120
|
+
split[0] = split[0].replace(
|
121
|
+
/(\d)(?=(\d\d\d)+(?!\d))/g,
|
122
|
+
'$1' + delimiter
|
123
|
+
);
|
124
|
+
return split.join('.');
|
125
|
+
};
|
126
|
+
|
107
127
|
$(function(){
|
108
128
|
realtimeGraph();
|
109
129
|
historyGraph();
|
data/web/views/_summary.slim
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
ul.unstyled.summary
|
2
|
-
li
|
2
|
+
li.processed
|
3
3
|
span.count #{number_with_delimiter(stats.processed)}
|
4
4
|
span.desc Processed
|
5
|
-
li
|
5
|
+
li.failed
|
6
6
|
span.count #{number_with_delimiter(stats.failed)}
|
7
7
|
span.desc Failed
|
8
8
|
li
|
9
9
|
span.count #{number_with_delimiter(workers.size)}
|
10
10
|
span.desc Busy
|
11
|
-
li
|
12
|
-
span.count #{number_with_delimiter(
|
11
|
+
li.scheduled
|
12
|
+
span.count #{number_with_delimiter(stats.scheduled_size)}
|
13
13
|
span.desc Scheduled
|
14
|
-
li
|
15
|
-
span.count #{number_with_delimiter(
|
14
|
+
li.retries
|
15
|
+
span.count #{number_with_delimiter(stats.retry_size)}
|
16
16
|
span.desc Retries
|
17
|
-
li
|
17
|
+
li.enqueued
|
18
18
|
span.count #{number_with_delimiter(stats.enqueued)}
|
19
19
|
span.desc Enqueued
|
data/web/views/dashboard.slim
CHANGED
@@ -15,22 +15,27 @@ h5
|
|
15
15
|
br
|
16
16
|
h5 Redis
|
17
17
|
|
18
|
-
.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
.
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
.stat
|
35
|
-
|
36
|
-
|
18
|
+
- if @redis_info.fetch("redis_version", nil)
|
19
|
+
.stat
|
20
|
+
h3= @redis_info.fetch("redis_version")
|
21
|
+
p Version
|
22
|
+
|
23
|
+
- if @redis_info.fetch("uptime_in_days", nil)
|
24
|
+
.stat
|
25
|
+
h3= @redis_info.fetch("uptime_in_days")
|
26
|
+
p Uptime (days)
|
27
|
+
|
28
|
+
- if @redis_info.fetch("connected_clients", nil)
|
29
|
+
.stat
|
30
|
+
h3= @redis_info.fetch("connected_clients")
|
31
|
+
p Connections
|
32
|
+
|
33
|
+
- if @redis_info.fetch("used_memory_human", nil)
|
34
|
+
.stat
|
35
|
+
h3= @redis_info.fetch("used_memory_human")
|
36
|
+
p Memory Usage
|
37
|
+
|
38
|
+
- if @redis_info.fetch("used_memory_peak_human", nil)
|
39
|
+
.stat
|
40
|
+
h3= @redis_info.fetch("used_memory_peak_human")
|
41
|
+
p Peak Memory Usage
|
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: 2.6.
|
4
|
+
version: 2.6.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 0
|
53
|
+
version: '1.0'
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0
|
61
|
+
version: '1.0'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: celluloid
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -245,7 +245,6 @@ files:
|
|
245
245
|
- lib/sidekiq/rails.rb
|
246
246
|
- lib/sidekiq/redis_connection.rb
|
247
247
|
- lib/sidekiq/scheduled.rb
|
248
|
-
- lib/sidekiq/stats.rb
|
249
248
|
- lib/sidekiq/testing.rb
|
250
249
|
- lib/sidekiq/testing/inline.rb
|
251
250
|
- lib/sidekiq/util.rb
|
data/lib/sidekiq/stats.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
module Sidekiq
|
2
|
-
module_function
|
3
|
-
|
4
|
-
def size(*queues)
|
5
|
-
return Sidekiq::Stats.new.enqueued if queues.empty?
|
6
|
-
|
7
|
-
Sidekiq.redis { |conn|
|
8
|
-
conn.multi {
|
9
|
-
queues.map { |q| conn.llen("queue:#{q}") }
|
10
|
-
}
|
11
|
-
}.inject(0) { |memo, count| memo += count }
|
12
|
-
end
|
13
|
-
end
|