sidekiq 0.10.0 → 0.10.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
+ 0.10.1
2
+ -----------
3
+
4
+ - Add details page for jobs in retry queue (jcoene)
5
+ - Display relative timestamps in web interface (jcoene)
6
+ - Capistrano fixes (hinrik, bensie)
7
+
1
8
  0.10.0
2
9
  -----------
3
10
 
@@ -2,42 +2,73 @@
2
2
 
3
3
  require 'fileutils'
4
4
 
5
- stage = ARGV[0]
6
- pidfile = ARGV[1]
7
- timeout = ARGV[2].to_i
8
- timeout = 10 if timeout == 0
5
+ class Sidekiqctl
9
6
 
10
- def done(msg)
11
- puts msg
12
- exit(0)
13
- end
7
+ attr_reader :stage, :pidfile, :timeout
14
8
 
15
- done 'No pidfile given' if !pidfile
16
- done 'Pidfile does not exist' if !File.exist?(pidfile)
9
+ def initialize(stage, pidfile, timeout)
10
+ @stage = stage
11
+ @pidfile = pidfile
12
+ @timeout = timeout
17
13
 
18
- pid = File.read(pidfile).to_i
19
- done 'Invalid pidfile content' if pid == 0
14
+ done 'No pidfile given' if !pidfile
15
+ done 'Pidfile does not exist' if !File.exist?(pidfile)
16
+ done 'Invalid pidfile content' if pid == 0
20
17
 
21
- begin
22
- Process.getpgid(pid)
23
- rescue Errno::ESRCH
24
- done "Process doesn't exist"
25
- end
18
+ fetch_process
26
19
 
27
- case stage
28
- when 'quiet'
29
- `kill -USR1 #{pid}`
30
- when 'stop'
31
- `kill -TERM #{pid}`
32
- timeout.times do
33
20
  begin
34
- Process.getpgid(pid)
35
- rescue Errno::ESRCH
36
- FileUtils.rm_f pidfile
37
- done 'Sidekiq shut down gracefully.'
21
+ send(stage)
22
+ rescue NoMethodError
23
+ done 'Invalid control command'
24
+ end
25
+ end
26
+
27
+ def fetch_process
28
+ Process.getpgid(pid)
29
+ rescue Errno::ESRCH
30
+ done "Process doesn't exist"
31
+ end
32
+
33
+ def done(msg)
34
+ puts msg
35
+ exit(0)
36
+ end
37
+
38
+ def pid
39
+ File.read(pidfile).to_i
40
+ end
41
+
42
+ def quiet
43
+ `kill -USR1 #{pid}`
44
+ end
45
+
46
+ def stop
47
+ `kill -TERM #{pid}`
48
+ timeout.times do
49
+ begin
50
+ Process.getpgid(pid)
51
+ rescue Errno::ESRCH
52
+ FileUtils.rm_f pidfile
53
+ done 'Sidekiq shut down gracefully.'
54
+ end
55
+ sleep 1
38
56
  end
39
- sleep 1
57
+ `kill -9 #{pid}`
58
+ FileUtils.rm_f pidfile
59
+ done 'Sidekiq shut down forcefully.'
40
60
  end
41
- `kill -9 #{pid}`
42
- done 'Sidekiq shut down forcefully.'
61
+
62
+ def shutdown
63
+ quiet
64
+ stop
65
+ end
66
+
43
67
  end
68
+
69
+ stage = ARGV[0]
70
+ pidfile = ARGV[1]
71
+ timeout = ARGV[2].to_i
72
+ timeout = 10 if timeout == 0
73
+
74
+ Sidekiqctl.new(stage, pidfile, timeout)
data/config.ru CHANGED
@@ -4,5 +4,15 @@ Sidekiq.configure_client do |config|
4
4
  config.redis = { :size => 1 }
5
5
  end
6
6
 
7
+ #Sidekiq.redis {|conn| conn.flushdb }
8
+ #10.times do |idx|
9
+ #Sidekiq::Client.push('class' => 'HardWorker', 'args' => ['foo', 0.1, idx])
10
+ #end
11
+
12
+ #Sidekiq.redis { |conn| conn.zadd('retry', Time.now.utc.to_f + 3000, MultiJson.encode({
13
+ #'class' => 'HardWorker', 'args' => ['foo', 0.1, Time.now.to_f],
14
+ #'queue' => 'default', 'error_message' => 'No such method', 'error_class' => 'NoMethodError',
15
+ #'failed_at' => Time.now.utc, 'retry_count' => 0 })) }
16
+
7
17
  require 'sidekiq/web'
8
18
  run Sidekiq::Web
@@ -56,32 +56,15 @@ module Sidekiq
56
56
 
57
57
  def self.redis(&block)
58
58
  @redis ||= Sidekiq::RedisConnection.create
59
- if block_given?
60
- @redis.with(&block)
61
- else
62
- Sidekiq::Util.logger.info "*****************************************************
63
- Sidekiq.redis now takes a block:
64
-
65
- Sidekiq.redis { |connection| connection.smembers('myset') }
66
-
67
- Please update your code accordingly.
68
- Called from #{caller[0]}
69
- *****************************************************"
70
- @redis
71
- end
59
+ raise ArgumentError, "requires a block" if !block
60
+ @redis.with(&block)
72
61
  end
73
62
 
74
63
  def self.redis=(hash)
75
- @redis = if hash.is_a?(Hash)
76
- RedisConnection.create(hash)
64
+ if hash.is_a?(Hash)
65
+ @redis = RedisConnection.create(hash)
77
66
  else
78
- Sidekiq::Util.logger.info "*****************************************************
79
- Sidekiq.redis now takes a Hash:
80
- old: Sidekiq.redis = Sidekiq::RedisConnection.create(:url => 'redis://foo.com', :namespace => 'abc', :size => 12)
81
- new: Sidekiq.redis = { :url => 'redis://foo.com', :namespace => 'xyz', :size => 12 }
82
- Called from #{caller[0]}
83
- *****************************************************"
84
- hash
67
+ @redis = hash
85
68
  end
86
69
  end
87
70
 
@@ -8,18 +8,18 @@ Capistrano::Configuration.instance.load do
8
8
 
9
9
  desc "Quiet sidekiq (stop accepting new work)"
10
10
  task :quiet do
11
- run "cd #{current_path} && sidekiqctl quiet #{current_path}/tmp/pids/sidekiq.pid"
11
+ run "cd #{current_path} && bundle exec sidekiqctl quiet #{current_path}/tmp/pids/sidekiq.pid"
12
12
  end
13
13
 
14
14
  desc "Stop sidekiq"
15
15
  task :stop do
16
- run "cd #{current_path} && sidekiqctl stop #{current_path}/tmp/pids/sidekiq.pid #{fetch :sidekiq_timeout}"
16
+ run "cd #{current_path} && bundle exec sidekiqctl stop #{current_path}/tmp/pids/sidekiq.pid #{fetch :sidekiq_timeout}"
17
17
  end
18
18
 
19
19
  desc "Start sidekiq"
20
20
  task :start do
21
21
  rails_env = fetch(:rails_env, "production")
22
- run "cd #{current_path} && nohup bundle exec sidekiq -e #{rails_env} -C #{current_path}/config/sidekiq.yml -P #{current_path}/tmp/pids/sidekiq.pid >> #{current_path}/log/sidekiq.log 2>&1 &"
22
+ run "cd #{current_path} ; nohup bundle exec sidekiq -e #{rails_env} -C #{current_path}/config/sidekiq.yml -P #{current_path}/tmp/pids/sidekiq.pid >> #{current_path}/log/sidekiq.log 2>&1 &"
23
23
  end
24
24
 
25
25
  desc "Restart sidekiq"
@@ -12,10 +12,6 @@ module Sidekiq
12
12
  include Util
13
13
  include Celluloid
14
14
 
15
- def self.middleware
16
- raise "Sidekiq::Processor.middleware is now Sidekiq.server_middleware"
17
- end
18
-
19
15
  def self.default_middleware
20
16
  Middleware::Chain.new do |m|
21
17
  m.add Middleware::Server::ExceptionHandler
@@ -1,3 +1,3 @@
1
1
  module Sidekiq
2
- VERSION = "0.10.0"
2
+ VERSION = "0.10.1"
3
3
  end
@@ -36,6 +36,16 @@ module Sidekiq
36
36
  use SprocketsMiddleware, :root => dir
37
37
 
38
38
  helpers do
39
+
40
+ def reset_worker_list
41
+ Sidekiq.redis do |conn|
42
+ workers = conn.smembers('workers')
43
+ workers.each do |name|
44
+ conn.srem('workers', name) # if name =~ /:#{process_id}-/
45
+ end
46
+ end
47
+ end
48
+
39
49
  def workers
40
50
  @workers ||= begin
41
51
  Sidekiq.redis do |conn|
@@ -75,6 +85,13 @@ module Sidekiq
75
85
  end
76
86
  end
77
87
 
88
+ def retries_with_score(score)
89
+ Sidekiq.redis do |conn|
90
+ results = conn.zrangebyscore('retry', score, score)
91
+ results.map { |msg| MultiJson.decode(msg) }
92
+ end
93
+ end
94
+
78
95
  def location
79
96
  Sidekiq.redis { |conn| conn.client.location }
80
97
  end
@@ -88,18 +105,53 @@ module Sidekiq
88
105
  return 'idle' if workers.size > 0 && workers.map { |x| x[1] }.compact.size == 0
89
106
  return 'active'
90
107
  end
108
+
109
+ def relative_time(time)
110
+ "<time datetime=\"#{time.getutc.iso8601}\">#{time}</time>"
111
+ end
91
112
  end
92
113
 
93
114
  get "/" do
94
115
  slim :index
95
116
  end
96
117
 
118
+ post "/reset" do
119
+ reset_worker_list
120
+ redirect root_path
121
+ end
122
+
97
123
  get "/queues/:name" do
98
124
  halt 404 unless params[:name]
99
125
  @name = params[:name]
100
126
  @messages = Sidekiq.redis {|conn| conn.lrange("queue:#{@name}", 0, 10) }.map { |str| MultiJson.decode(str) }
101
127
  slim :queue
102
128
  end
129
+
130
+ get "/retries/:score" do
131
+ halt 404 unless params[:score]
132
+ @score = params[:score].to_f
133
+ slim :retry
134
+ end
135
+
136
+ post "/retries/:score" do
137
+ halt 404 unless params[:score]
138
+ score = params[:score].to_f
139
+ if params['retry']
140
+ Sidekiq.redis do |conn|
141
+ results = conn.zrangebyscore('retry', score, score)
142
+ conn.zremrangebyscore('retry', score, score)
143
+ results.map do |message|
144
+ msg = MultiJson.decode(message)
145
+ conn.rpush("queue:#{msg['queue']}", message)
146
+ end
147
+ end
148
+ elsif params['delete']
149
+ Sidekiq.redis do |conn|
150
+ conn.zremrangebyscore('retry', score, score)
151
+ end
152
+ end
153
+ redirect root_path
154
+ end
103
155
  end
104
156
 
105
157
  end
@@ -6,7 +6,7 @@ class TestClient < MiniTest::Unit::TestCase
6
6
  describe 'with real redis' do
7
7
  before do
8
8
  Sidekiq.redis = REDIS
9
- Sidekiq.redis.flushdb
9
+ Sidekiq.redis {|c| c.flushdb }
10
10
  end
11
11
 
12
12
  it 'does not push duplicate messages when configured for unique only' do
@@ -15,13 +15,13 @@ class TestClient < MiniTest::Unit::TestCase
15
15
  chain.add Sidekiq::Middleware::Client::UniqueJobs
16
16
  end
17
17
  10.times { Sidekiq::Client.push('customqueue', 'class' => 'Foo', 'args' => [1, 2]) }
18
- assert_equal 1, Sidekiq.redis.llen("queue:customqueue")
18
+ assert_equal 1, Sidekiq.redis {|c| c.llen("queue:customqueue") }
19
19
  end
20
20
 
21
21
  it 'does push duplicate messages when not configured for unique only' do
22
22
  Sidekiq.client_middleware.remove(Sidekiq::Middleware::Client::UniqueJobs)
23
23
  10.times { Sidekiq::Client.push('customqueue2', 'class' => 'Foo', 'args' => [1, 2]) }
24
- assert_equal 10, Sidekiq.redis.llen("queue:customqueue2")
24
+ assert_equal 10, Sidekiq.redis {|c| c.llen("queue:customqueue2") }
25
25
  end
26
26
  end
27
27
 
@@ -11,7 +11,7 @@ class TestExtensions < MiniTest::Unit::TestCase
11
11
  describe 'sidekiq extensions' do
12
12
  before do
13
13
  Sidekiq.redis = REDIS
14
- Sidekiq.redis.flushdb
14
+ Sidekiq.redis {|c| c.flushdb }
15
15
  end
16
16
 
17
17
  class MyModel < ActiveRecord::Base
@@ -22,10 +22,10 @@ class TestExtensions < MiniTest::Unit::TestCase
22
22
 
23
23
  it 'allows delayed exection of ActiveRecord class methods' do
24
24
  assert_equal [], Sidekiq::Client.registered_queues
25
- assert_equal 0, Sidekiq.redis.llen('queue:default')
25
+ assert_equal 0, Sidekiq.redis {|c| c.llen('queue:default') }
26
26
  MyModel.delay.long_class_method
27
27
  assert_equal ['default'], Sidekiq::Client.registered_queues
28
- assert_equal 1, Sidekiq.redis.llen('queue:default')
28
+ assert_equal 1, Sidekiq.redis {|c| c.llen('queue:default') }
29
29
  end
30
30
 
31
31
  class UserMailer < ActionMailer::Base
@@ -36,10 +36,10 @@ class TestExtensions < MiniTest::Unit::TestCase
36
36
 
37
37
  it 'allows delayed delivery of ActionMailer mails' do
38
38
  assert_equal [], Sidekiq::Client.registered_queues
39
- assert_equal 0, Sidekiq.redis.llen('queue:default')
39
+ assert_equal 0, Sidekiq.redis {|c| c.llen('queue:default') }
40
40
  UserMailer.delay.greetings(1, 2)
41
41
  assert_equal ['default'], Sidekiq::Client.registered_queues
42
- assert_equal 1, Sidekiq.redis.llen('queue:default')
42
+ assert_equal 1, Sidekiq.redis {|c| c.llen('queue:default') }
43
43
  end
44
44
  end
45
45
 
@@ -9,7 +9,7 @@ class TestManager < MiniTest::Unit::TestCase
9
9
  describe 'with redis' do
10
10
  before do
11
11
  Sidekiq.redis = REDIS
12
- Sidekiq.redis.flushdb
12
+ Sidekiq.redis {|c| c.flushdb }
13
13
  $processed = 0
14
14
  $mutex = Mutex.new
15
15
  end
@@ -6,7 +6,7 @@ class TestStats < MiniTest::Unit::TestCase
6
6
  describe 'with redis' do
7
7
  before do
8
8
  @redis = Sidekiq.redis = REDIS
9
- Sidekiq.redis.flushdb
9
+ Sidekiq.redis {|c| c.flushdb }
10
10
  end
11
11
 
12
12
  class DumbWorker
@@ -13,7 +13,7 @@ class TestWeb < MiniTest::Unit::TestCase
13
13
 
14
14
  before do
15
15
  Sidekiq.redis = REDIS
16
- Sidekiq.redis.flushdb
16
+ Sidekiq.redis {|c| c.flushdb }
17
17
  end
18
18
 
19
19
  class WebWorker
@@ -1,3 +1,9 @@
1
1
  //= require vendor/jquery
2
+ //= require vendor/jquery.timeago
2
3
  //= require bootstrap
3
4
  //= require_tree .
5
+
6
+ jQuery(document).ready(function() {
7
+ jQuery.timeago.settings.allowFuture = true
8
+ jQuery("time").timeago();
9
+ });
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Timeago is a jQuery plugin that makes it easy to support automatically
3
+ * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
4
+ *
5
+ * @name timeago
6
+ * @version 0.11.1
7
+ * @requires jQuery v1.2.3+
8
+ * @author Ryan McGeary
9
+ * @license MIT License - http://www.opensource.org/licenses/mit-license.php
10
+ *
11
+ * For usage and examples, visit:
12
+ * http://timeago.yarp.com/
13
+ *
14
+ * Copyright (c) 2008-2011, Ryan McGeary (ryanonjavascript -[at]- mcgeary [*dot*] org)
15
+ */
16
+ (function($) {
17
+ $.timeago = function(timestamp) {
18
+ if (timestamp instanceof Date) {
19
+ return inWords(timestamp);
20
+ } else if (typeof timestamp === "string") {
21
+ return inWords($.timeago.parse(timestamp));
22
+ } else {
23
+ return inWords($.timeago.datetime(timestamp));
24
+ }
25
+ };
26
+ var $t = $.timeago;
27
+
28
+ $.extend($.timeago, {
29
+ settings: {
30
+ refreshMillis: 60000,
31
+ allowFuture: false,
32
+ strings: {
33
+ prefixAgo: null,
34
+ prefixFromNow: null,
35
+ suffixAgo: "ago",
36
+ suffixFromNow: "from now",
37
+ seconds: "less than a minute",
38
+ minute: "about a minute",
39
+ minutes: "%d minutes",
40
+ hour: "about an hour",
41
+ hours: "about %d hours",
42
+ day: "a day",
43
+ days: "%d days",
44
+ month: "about a month",
45
+ months: "%d months",
46
+ year: "about a year",
47
+ years: "%d years",
48
+ wordSeparator: " ",
49
+ numbers: []
50
+ }
51
+ },
52
+ inWords: function(distanceMillis) {
53
+ var $l = this.settings.strings;
54
+ var prefix = $l.prefixAgo;
55
+ var suffix = $l.suffixAgo;
56
+ if (this.settings.allowFuture) {
57
+ if (distanceMillis < 0) {
58
+ prefix = $l.prefixFromNow;
59
+ suffix = $l.suffixFromNow;
60
+ }
61
+ }
62
+
63
+ var seconds = Math.abs(distanceMillis) / 1000;
64
+ var minutes = seconds / 60;
65
+ var hours = minutes / 60;
66
+ var days = hours / 24;
67
+ var years = days / 365;
68
+
69
+ function substitute(stringOrFunction, number) {
70
+ var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
71
+ var value = ($l.numbers && $l.numbers[number]) || number;
72
+ return string.replace(/%d/i, value);
73
+ }
74
+
75
+ var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
76
+ seconds < 90 && substitute($l.minute, 1) ||
77
+ minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
78
+ minutes < 90 && substitute($l.hour, 1) ||
79
+ hours < 24 && substitute($l.hours, Math.round(hours)) ||
80
+ hours < 42 && substitute($l.day, 1) ||
81
+ days < 30 && substitute($l.days, Math.round(days)) ||
82
+ days < 45 && substitute($l.month, 1) ||
83
+ days < 365 && substitute($l.months, Math.round(days / 30)) ||
84
+ years < 1.5 && substitute($l.year, 1) ||
85
+ substitute($l.years, Math.round(years));
86
+
87
+ var separator = $l.wordSeparator === undefined ? " " : $l.wordSeparator;
88
+ return $.trim([prefix, words, suffix].join(separator));
89
+ },
90
+ parse: function(iso8601) {
91
+ var s = $.trim(iso8601);
92
+ s = s.replace(/\.\d\d\d+/,""); // remove milliseconds
93
+ s = s.replace(/-/,"/").replace(/-/,"/");
94
+ s = s.replace(/T/," ").replace(/Z/," UTC");
95
+ s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
96
+ return new Date(s);
97
+ },
98
+ datetime: function(elem) {
99
+ // jQuery's `is()` doesn't play well with HTML5 in IE
100
+ var isTime = $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
101
+ var iso8601 = isTime ? $(elem).attr("datetime") : $(elem).attr("title");
102
+ return $t.parse(iso8601);
103
+ }
104
+ });
105
+
106
+ $.fn.timeago = function() {
107
+ var self = this;
108
+ self.each(refresh);
109
+
110
+ var $s = $t.settings;
111
+ if ($s.refreshMillis > 0) {
112
+ setInterval(function() { self.each(refresh); }, $s.refreshMillis);
113
+ }
114
+ return self;
115
+ };
116
+
117
+ function refresh() {
118
+ var data = prepareData(this);
119
+ if (!isNaN(data.datetime)) {
120
+ $(this).text(inWords(data.datetime));
121
+ }
122
+ return this;
123
+ }
124
+
125
+ function prepareData(element) {
126
+ element = $(element);
127
+ if (!element.data("timeago")) {
128
+ element.data("timeago", { datetime: $t.datetime(element) });
129
+ var text = $.trim(element.text());
130
+ if (text.length > 0) {
131
+ element.attr("title", text);
132
+ }
133
+ }
134
+ return element.data("timeago");
135
+ }
136
+
137
+ function inWords(date) {
138
+ return $t.inWords(distance(date));
139
+ }
140
+
141
+ function distance(date) {
142
+ return (new Date().getTime() - date.getTime());
143
+ }
144
+
145
+ // fix for IE6 suckage
146
+ document.createElement("abbr");
147
+ document.createElement("time");
148
+ }(jQuery));
@@ -22,6 +22,7 @@
22
22
  th Queue
23
23
  th Class
24
24
  th Arguments
25
+ th Started
25
26
  - workers.each do |(worker, msg)|
26
27
  tr
27
28
  td= worker
@@ -29,8 +30,11 @@
29
30
  td= msg['queue']
30
31
  td= msg['payload']['class']
31
32
  td= msg['payload']['args'].inspect[0..100]
33
+ td== relative_time(Time.parse(msg['run_at']))
32
34
  - else
33
- td colspan=3 Idle
35
+ td colspan=4 Idle
36
+ form action="#{root_path}reset" method="post"
37
+ button.btn type="submit" Clear worker list
34
38
 
35
39
  #queues.tab-pane
36
40
  table class="table table-striped table-bordered"
@@ -53,7 +57,8 @@
53
57
  th Args
54
58
  - retries.each do |(msg, score)|
55
59
  tr
56
- td= Time.at(score)
60
+ td
61
+ a href="retries/#{score}"== relative_time(Time.at(score))
57
62
  td= msg['retry_count']
58
63
  td
59
64
  a href="queues/#{msg['queue']}" #{msg['queue']}
@@ -0,0 +1,44 @@
1
+ header
2
+ h1 Retry Job
3
+
4
+ - retries_with_score(@score).each do |msg|
5
+ table class="table table-striped table-bordered"
6
+ tbody
7
+ tr
8
+ th Queue
9
+ td
10
+ a href="#{root_path}queues/#{msg['queue']}" #{msg['queue']}
11
+ tr
12
+ th Job Class
13
+ td
14
+ code= msg['class']
15
+ tr
16
+ th Job Arguments
17
+ td
18
+ code= msg['args'].inspect[0..1000]
19
+ tr
20
+ th Error Class
21
+ td
22
+ code= msg['error_class']
23
+ tr
24
+ th Error Message
25
+ td= msg['error_message']
26
+ - if msg['retry_count'] > 0
27
+ tr
28
+ th Retry Count
29
+ td= msg['retry_count']
30
+ tr
31
+ th Last Retry
32
+ td== relative_time(Time.parse(msg['retried_at']))
33
+ - else
34
+ tr
35
+ th Originally Failed
36
+ td== relative_time(Time.parse(msg['failed_at']))
37
+ tr
38
+ th Next Retry
39
+ td== relative_time(Time.at(@score))
40
+
41
+ form.form-horizontal action="#{root_path}retries/#{@score}" method="post"
42
+ a.btn href="#{root_path}" &larr; Back
43
+ input.btn.btn-primary type="submit" name="retry" value="Retry Now"
44
+ 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: 0.10.0
4
+ version: 0.10.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-03-28 00:00:00.000000000 Z
12
+ date: 2012-03-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
16
- requirement: &70249655983600 !ruby/object:Gem::Requirement
16
+ requirement: &70182756998440 !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: *70249655983600
24
+ version_requirements: *70182756998440
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: redis-namespace
27
- requirement: &70249655982380 !ruby/object:Gem::Requirement
27
+ requirement: &70182756997620 !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: *70249655982380
35
+ version_requirements: *70182756997620
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: connection_pool
38
- requirement: &70249655981700 !ruby/object:Gem::Requirement
38
+ requirement: &70182756997120 !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: *70249655981700
46
+ version_requirements: *70182756997120
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: celluloid
49
- requirement: &70249655981280 !ruby/object:Gem::Requirement
49
+ requirement: &70182756996700 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70249655981280
57
+ version_requirements: *70182756996700
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: multi_json
60
- requirement: &70249655980820 !ruby/object:Gem::Requirement
60
+ requirement: &70182756996240 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70249655980820
68
+ version_requirements: *70182756996240
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: minitest
71
- requirement: &70249655980400 !ruby/object:Gem::Requirement
71
+ requirement: &70182757019360 !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: *70249655980400
79
+ version_requirements: *70182757019360
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: sinatra
82
- requirement: &70249656007360 !ruby/object:Gem::Requirement
82
+ requirement: &70182757018940 !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: *70249656007360
90
+ version_requirements: *70182757018940
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: slim
93
- requirement: &70249656006940 !ruby/object:Gem::Requirement
93
+ requirement: &70182757018520 !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: *70249656006940
101
+ version_requirements: *70182757018520
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: rake
104
- requirement: &70249656006520 !ruby/object:Gem::Requirement
104
+ requirement: &70182757018100 !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: *70249656006520
112
+ version_requirements: *70182757018100
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: actionmailer
115
- requirement: &70249656006020 !ruby/object:Gem::Requirement
115
+ requirement: &70182757017600 !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: *70249656006020
123
+ version_requirements: *70182757017600
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: activerecord
126
- requirement: &70249656005520 !ruby/object:Gem::Requirement
126
+ requirement: &70182757017040 !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: *70249656005520
134
+ version_requirements: *70182757017040
135
135
  description: Simple, efficient message processing for Ruby
136
136
  email:
137
137
  - mperham@gmail.com
@@ -261,12 +261,14 @@ files:
261
261
  - web/assets/javascripts/vendor/bootstrap/bootstrap-transition.js
262
262
  - web/assets/javascripts/vendor/bootstrap/bootstrap-typeahead.js
263
263
  - web/assets/javascripts/vendor/jquery.js
264
+ - web/assets/javascripts/vendor/jquery.timeago.js
264
265
  - web/assets/stylesheets/application.css
265
266
  - web/assets/stylesheets/vendor/bootstrap-responsive.css
266
267
  - web/assets/stylesheets/vendor/bootstrap.css
267
268
  - web/views/index.slim
268
269
  - web/views/layout.slim
269
270
  - web/views/queue.slim
271
+ - web/views/retry.slim
270
272
  homepage: http://mperham.github.com/sidekiq
271
273
  licenses: []
272
274
  post_install_message: