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 CHANGED
@@ -1,3 +1,10 @@
1
+ 2.6.1
2
+ -----------
3
+
4
+ - Dashboard now live updates summary stats also. [brandonhilkert, #605]
5
+ - Add middleware chain APIs `insert_before` and `insert_after` for fine
6
+ tuning the order of middleware. [jackrg, #595]
7
+
1
8
  2.6.0
2
9
  -----------
3
10
 
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
- and 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!
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
 
@@ -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
@@ -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
@@ -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" }
@@ -60,8 +60,15 @@ rescue LoadError
60
60
  self[key.to_s] = delete(key)
61
61
  end
62
62
  self
63
- end
64
- end if !{}.respond_to?(:stringify_keys)
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
@@ -43,8 +43,8 @@ module Sidekiq
43
43
  worker.perform(*cloned(msg['args']))
44
44
  end
45
45
  end
46
- rescue Exception => ex
47
- handle_exception(ex, msg || { :message => msgstr })
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)
@@ -1,3 +1,3 @@
1
1
  module Sidekiq
2
- VERSION = "2.6.0"
2
+ VERSION = "2.6.1"
3
3
  end
@@ -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({ processed: stats.processed, failed: stats.failed })
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
@@ -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.9.2'
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'
@@ -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
@@ -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();
@@ -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(scheduled_job_count)}
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(retry_job_count)}
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
@@ -15,22 +15,27 @@ h5
15
15
  br
16
16
  h5 Redis
17
17
 
18
- .stat
19
- h3= @redis_info.fetch("redis_version")
20
- p Version
21
-
22
- .stat
23
- h3= @redis_info.fetch("uptime_in_days")
24
- p Uptime (days)
25
-
26
- .stat
27
- h3= @redis_info.fetch("connected_clients")
28
- p Connections
29
-
30
- .stat
31
- h3= @redis_info.fetch("used_memory_human")
32
- p Memory Usage
33
-
34
- .stat
35
- h3= @redis_info.fetch("used_memory_peak_human")
36
- p Peak Memory Usage
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.0
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-16 00:00:00.000000000 Z
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.9.2
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.9.2
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
@@ -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