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 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
@@ -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
@@ -10,11 +10,18 @@ trap 'TERM' do
10
10
  end
11
11
 
12
12
  trap 'USR1' do
13
- Sidekiq::Util.logger.info "Received USR1, no longer accepting new work"
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::Util.logger
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::Util.logger.level = Logger::DEBUG if options[:verbose]
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::Util.logger.level = Logger::DEBUG
137
+ Sidekiq.logger.level = ::Logger::DEBUG
131
138
  end
132
139
 
133
140
  o.on '-e', '--environment ENV', "Application environment" do |arg|
@@ -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
@@ -39,6 +39,7 @@ module Sidekiq
39
39
  timeout = options[:timeout]
40
40
 
41
41
  @done = true
42
+ Sidekiq::Fetcher.done!
42
43
  @fetcher.terminate! if @fetcher.alive?
43
44
 
44
45
  logger.info { "Shutting down #{@ready.size} quiet workers" }
@@ -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
- static = "#{args[0].class.to_s} MSG-#{args[0].object_id.to_s(36)}" if logger.info?
7
- start = Time.now
8
- logger.info { "#{static} start" }
9
- yield
10
- logger.info { "#{static} done: #{elapsed(start)} sec" }
11
- rescue
12
- logger.info { "#{static} fail: #{elapsed(start)} sec" }
13
- raise
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::Util.logger
25
+ Sidekiq.logger
22
26
  end
23
27
  end
24
28
  end
@@ -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", DEFAULT_EXPIRY, Time.now.to_s)
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}", DEFAULT_EXPIRY, Sidekiq.dump_json(hash))
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
@@ -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
- DEFAULT_EXPIRY = 24 * 60 * 60
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::Util.logger
29
+ Sidekiq.logger
53
30
  end
54
31
 
55
32
  def redis(&block)
@@ -1,3 +1,3 @@
1
1
  module Sidekiq
2
- VERSION = "1.2.0"
2
+ VERSION = "1.2.1"
3
3
  end
@@ -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, 25, :withscores => true)
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
- elsif params['delete']
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
@@ -24,6 +24,10 @@ module Sidekiq
24
24
  base.extend(ClassMethods)
25
25
  end
26
26
 
27
+ def logger
28
+ Sidekiq.logger
29
+ end
30
+
27
31
  module ClassMethods
28
32
  def perform_async(*args)
29
33
  Sidekiq::Client.push('class' => self, 'args' => args)
@@ -4,7 +4,7 @@ class HardWorker
4
4
 
5
5
  def perform(name, count, salt)
6
6
  raise name if name == 'crash'
7
- print "#{Time.now}\n"
7
+ logger.info Time.now
8
8
  sleep count
9
9
  end
10
10
  end
@@ -10,7 +10,7 @@ require 'minitest/autorun'
10
10
 
11
11
  require 'sidekiq'
12
12
  require 'sidekiq/util'
13
- Sidekiq::Util.logger.level = Logger::ERROR
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')
@@ -51,11 +51,11 @@ class TestCli < MiniTest::Unit::TestCase
51
51
  end
52
52
 
53
53
  it 'sets verbose' do
54
- old = Sidekiq::Util.logger.level
54
+ old = Sidekiq.logger.level
55
55
  @cli.parse(['sidekiq', '-v', '-r', './test/fake_env.rb'])
56
- assert_equal Logger::DEBUG, Sidekiq::Util.logger.level
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::Util.logger.level = old
58
+ Sidekiq.logger.level = old
59
59
  end
60
60
 
61
61
  describe 'with pidfile' do
@@ -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
 
@@ -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 last_response.body, /Sidekiq is idle/
31
- refute_match last_response.body, /default/
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 last_response.body, /Sidekiq is idle/
38
- assert_match last_response.body, /default/
39
- refute_match last_response.body, /foo/
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 last_response.body, /Sidekiq is idle/
46
- assert_match last_response.body, /default/
47
- assert_match last_response.body, /foo/
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
- jQuery(document).ready(function() {
7
- jQuery.timeago.settings.allowFuture = true
8
- jQuery("time").timeago();
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
  });
@@ -21,3 +21,7 @@ code {
21
21
  border: 0;
22
22
  background-color: inherit;
23
23
  }
24
+
25
+ .hero-unit {
26
+ padding: 30px;
27
+ }
@@ -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
 
@@ -12,6 +12,8 @@ html
12
12
  ul.nav
13
13
  li
14
14
  a href='#{{root_path}}' Home
15
+ li
16
+ a href='#{{root_path}}retries' Retries
15
17
  ul.nav.pull-right
16
18
  li
17
19
  a Redis: #{location}
@@ -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
@@ -15,7 +15,7 @@ header
15
15
  tr
16
16
  th Job Arguments
17
17
  td
18
- code= msg['args'].inspect[0..1000]
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}" &larr; Back
50
+ a.btn href="#{root_path}retries" &larr; 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.0
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-07 00:00:00.000000000 Z
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: &70181602671160 !ruby/object:Gem::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: *70181602671160
24
+ version_requirements: *70113151847120
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: redis-namespace
27
- requirement: &70181602670700 !ruby/object:Gem::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: *70181602670700
35
+ version_requirements: *70113151845720
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: connection_pool
38
- requirement: &70181602669980 !ruby/object:Gem::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: *70181602669980
46
+ version_requirements: *70113151844280
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: celluloid
49
- requirement: &70181602669040 !ruby/object:Gem::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: *70181602669040
57
+ version_requirements: *70113151842720
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: multi_json
60
- requirement: &70181602668580 !ruby/object:Gem::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: *70181602668580
68
+ version_requirements: *70113151841480
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: minitest
71
- requirement: &70181602684540 !ruby/object:Gem::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: *70181602684540
79
+ version_requirements: *70113151840480
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: sinatra
82
- requirement: &70181602683860 !ruby/object:Gem::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: *70181602683860
90
+ version_requirements: *70113151839320
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: slim
93
- requirement: &70181602683240 !ruby/object:Gem::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: *70181602683240
101
+ version_requirements: *70113151838740
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: rake
104
- requirement: &70181602682820 !ruby/object:Gem::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: *70181602682820
112
+ version_requirements: *70113151837560
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: actionmailer
115
- requirement: &70181602682300 !ruby/object:Gem::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: *70181602682300
123
+ version_requirements: *70113151833660
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: activerecord
126
- requirement: &70181602681760 !ruby/object:Gem::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: *70181602681760
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: []