sidekiq 2.0.3 → 2.1.0

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.

@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - jruby-19mode
5
+ branches:
6
+ only:
7
+ - master
8
+ notifications:
9
+ irc: "irc.freenode.org#sidekiq"
10
+ email:
11
+ recipients:
12
+ - sidekiq@librelist.org
13
+ matrix:
14
+ allow_failures:
15
+ - rvm: jruby-19mode
data/Changes.md CHANGED
@@ -1,12 +1,23 @@
1
+ 2.1.0
2
+ -----------
3
+
4
+ - Tune Celluloid to no longer run message processing within a Fiber.
5
+ This gives us a full Thread stack and also lowers Sidekiq's memory
6
+ usage.
7
+ - Add pagination within the Web UI [#253]
8
+ - Specify which Redis driver to use: *hiredis* or *ruby* (default)
9
+ - Remove FailureJobs and UniqueJobs, which have been optional server
10
+ middleware. [#302]
11
+
1
12
  2.0.3
2
13
  -----------
3
- - Fix sidekiq-web's navbar on mobile devices and windows <= 980px (ezkl)
14
+ - Fix sidekiq-web's navbar on mobile devices and windows under 980px (ezkl)
4
15
  - Fix Capistrano task for first deploys [#259]
5
16
  - Worker subclasses now properly inherit sidekiq\_options set in
6
17
  their superclass [#221]
7
18
  - Add random jitter to scheduler to spread polls across POLL\_INTERVAL
8
19
  window. [#247]
9
- - Add note in README about new mailing list: sidekiq@librelist.org
20
+ - Sidekiq has a new mailing list: sidekiq@librelist.org See README.
10
21
 
11
22
  2.0.2
12
23
  -----------
data/Gemfile CHANGED
@@ -1,10 +1,11 @@
1
1
  source 'http://rubygems.org'
2
2
  gemspec
3
3
 
4
+ gem 'celluloid'
4
5
  gem 'slim'
5
6
  gem 'sprockets'
6
7
  gem 'sass'
7
- gem 'rails', '3.2.3'
8
+ gem 'rails', '3.2.6'
8
9
  gem 'sqlite3'
9
10
 
10
11
  group :test do
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- Sidekiq
1
+ Sidekiq [![Build Status](https://secure.travis-ci.org/mperham/sidekiq.png)](http://travis-ci.org/mperham/sidekiq)
2
2
  ==============
3
3
 
4
4
  Simple, efficient message processing for Ruby.
@@ -31,7 +31,7 @@ untested but I will do my best to support them. Ruby 1.8 is not supported.
31
31
  Installation
32
32
  -----------------
33
33
 
34
- gem install sidekiq
34
+ gem install sidekiq
35
35
 
36
36
 
37
37
  Getting Started
@@ -42,47 +42,10 @@ signal_worker() {
42
42
  if [ -f $PID_FILE ]; then
43
43
  set_pid_from_file
44
44
  logger -t "monit-sidekiq[$$]" "Issuing kill with -$SIG $PID"
45
- SLEEP_COUNT=0
46
45
  kill -$SIG $PID
47
46
  fi
48
47
  }
49
48
 
50
- signal_worker_fatally(){
51
- signal_worker()
52
- if [ -f $PID_FILE ]; then
53
- if [ -n "$ALLOW_TIMEOUT" ]; then
54
- while [ -e /proc/$PID ]; do
55
- sleep .25
56
- let "SLEEP_COUNT+=1"
57
- let "REPORT_TIME = $SLEEP_COUNT%4"
58
- if(( "$SLEEP_COUNT" > $GRACE_TIME )); then
59
- logger -t "monit-sidekiq[$$]" "Sidekiq worker with pid $PID for $WORKER_REF still running, issuing -TERM"
60
- kill -15 $PID 2>/dev/null; true
61
- elif(( $REPORT_TIME == 0 )); then
62
- let "RUNTIME = $SLEEP_COUNT/4"
63
- logger -t "monit-sidekiq[$$]" "waiting for $PID to die ( for $RUNTIME seconds now)"
64
- fi
65
- done
66
- fi
67
- sleep 1
68
- if [ -d /proc/$PID ];then
69
- for child in $(ps axo pid,ppid | awk "{ if ( \$2 == $PID ) { print \$1 }}");
70
- do
71
- kill -9 $child 2>/dev/null; true
72
- logger -t "monit-sidekiq[$$]" "Murdering Sidekiq workers child with $child for $WORKER_REF"
73
- break
74
- done
75
- while [ -d /proc/$PID ]; do
76
- logger -t "monit-sidekiq[$$]" "Murdering Sidekiq worker with $PID for $WORKER_REF"
77
- kill -9 $PID
78
- sleep 1
79
- done
80
- fi
81
- logger -t "monit-sidekiq[$$]" "Removing pid file for $PID - $WORKER_REF"
82
- [ -e "$PID_FILE" -a ! -d /proc/$PID ] && rm -f $PID_FILE
83
- fi
84
- }
85
-
86
49
  lock(){
87
50
  RESULT=0
88
51
  if [ -e $LOCK_FILE ]; then
@@ -146,14 +109,14 @@ else
146
109
  exit 1
147
110
  fi
148
111
 
149
- WORKER_REF=`echo $CONF_FILE | sed s/.conf//`
112
+ WORKER_REF=`echo $CONF_FILE | sed s/.yml//`
150
113
  LOG_FILE="$APP_ROOT/log/$WORKER_REF.log"
151
114
  LOCK_FILE="/tmp/$WORKER_REF.monit-lock"
152
115
  PID_FILE="/var/run/engineyard/sidekiq/$APP/$WORKER_REF.pid"
153
116
  GEMFILE="$APP_ROOT/Gemfile"
154
117
  SIDEKIQ="sidekiq"
155
118
  if [ -f $GEMFILE ];then
156
- SIDEKIQ="bundle exec $APP_ROOT/ey_bundler_binstubs/sidekiq"
119
+ SIDEKIQ="$APP_ROOT/ey_bundler_binstubs/sidekiq"
157
120
  fi
158
121
 
159
122
  if [ -d $APP_ROOT ]; then
@@ -201,8 +164,6 @@ if [ -d $APP_ROOT ]; then
201
164
  legacy_fix
202
165
  lock
203
166
  SIG="INT"
204
- [ -z "$GRACE_TIME" ] && GRACE_TIME=60
205
- ALLOW_TIMEOUT=1
206
167
  signal_worker
207
168
  [ -e "$LOCK_FILE" ] && rm $LOCK_FILE
208
169
  unlock_and_exit_cleanly
@@ -97,4 +97,12 @@ module Sidekiq
97
97
  Sidekiq::Logging.logger
98
98
  end
99
99
 
100
+ def self.logger=(log)
101
+ Sidekiq::Logging.logger = log
102
+ end
103
+
104
+ def self.poll_interval=(interval)
105
+ self.options[:poll_interval] = interval
106
+ end
107
+
100
108
  end
@@ -17,8 +17,8 @@ end
17
17
 
18
18
  trap 'TTIN' do
19
19
  Thread.list.each do |thread|
20
- puts "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
21
- puts thread.backtrace.join("\n")
20
+ Sidekiq.logger.info "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
21
+ Sidekiq.logger.info thread.backtrace.join("\n")
22
22
  end
23
23
  end
24
24
 
@@ -1,5 +1,4 @@
1
1
  require 'sidekiq/middleware/chain'
2
- require 'sidekiq/middleware/client/unique_jobs'
3
2
 
4
3
  module Sidekiq
5
4
  class Client
@@ -49,7 +48,7 @@ module Sidekiq
49
48
  payload = Sidekiq.dump_json(item)
50
49
  Sidekiq.redis do |conn|
51
50
  if item['at']
52
- pushed = (conn.zadd('schedule', item['at'].to_s, payload) == 1)
51
+ pushed = conn.zadd('schedule', item['at'].to_s, payload)
53
52
  else
54
53
  _, pushed = conn.multi do
55
54
  conn.sadd('queues', queue)
@@ -1,6 +1,6 @@
1
1
  module Sidekiq
2
2
  module Extensions
3
- class Proxy < (RUBY_VERSION < '1.9' ? Object : BasicObject)
3
+ class Proxy < BasicObject
4
4
  def initialize(performable, target, at=nil)
5
5
  @performable = performable
6
6
  @target = target
@@ -110,7 +110,7 @@ module Sidekiq
110
110
  processor = @ready.pop
111
111
  @in_progress[processor.object_id] = [msg, queue]
112
112
  @busy << processor
113
- processor.process!(Sidekiq.load_json(msg), queue)
113
+ processor.process!(msg, queue)
114
114
  end
115
115
  end
116
116
  end
@@ -7,22 +7,26 @@ module Sidekiq
7
7
  #
8
8
  # To add middleware for the client:
9
9
  #
10
- # Sidekiq.client_middleware do |chain|
11
- # chain.add MyClientHook
10
+ # Sidekiq.configure_client do |config|
11
+ # config.client_middleware do |chain|
12
+ # chain.add MyClientHook
13
+ # end
12
14
  # end
13
15
  #
14
16
  # To modify middleware for the server, just call
15
17
  # with another block:
16
18
  #
17
- # Sidekiq.server_middleware do |chain|
18
- # chain.add MyServerHook
19
- # chain.remove ActiveRecord
19
+ # Sidekiq.configure_server do |config|
20
+ # config.server_middleware do |chain|
21
+ # chain.add MyServerHook
22
+ # chain.remove ActiveRecord
23
+ # end
20
24
  # end
21
25
  #
22
26
  # This is an example of a minimal server middleware:
23
27
  #
24
28
  # class MyServerHook
25
- # def call(worker, msg, queue)
29
+ # def call(worker_instance, msg, queue)
26
30
  # puts "Before work"
27
31
  # yield
28
32
  # puts "After work"
@@ -32,7 +36,7 @@ module Sidekiq
32
36
  # This is an example of a minimal client middleware:
33
37
  #
34
38
  # class MyClientHook
35
- # def call(msg, queue)
39
+ # def call(worker_class, msg, queue)
36
40
  # puts "Before push"
37
41
  # yield
38
42
  # puts "After push"
@@ -0,0 +1,31 @@
1
+ module Sidekiq
2
+ module Paginator
3
+ def page(key, pageidx=1, page_size=25)
4
+ current_page = pageidx.to_i < 1 ? 1 : pageidx.to_i
5
+ pageidx = current_page - 1
6
+ total_size = 0
7
+ items = []
8
+ starting = pageidx * page_size
9
+ ending = starting + page_size - 1
10
+
11
+ Sidekiq.redis do |conn|
12
+ type = conn.type(key)
13
+
14
+ case type
15
+ when 'zset'
16
+ total_size = conn.zcard(key)
17
+ items = conn.zrange(key, starting, ending, :with_scores => true)
18
+ when 'list'
19
+ total_size = conn.llen(key)
20
+ items = conn.lrange(key, starting, ending)
21
+ when 'none'
22
+ return [1, 0, []]
23
+ else
24
+ raise "can't page a #{type}"
25
+ end
26
+ end
27
+
28
+ [current_page, total_size, items]
29
+ end
30
+ end
31
+ end
@@ -16,6 +16,8 @@ module Sidekiq
16
16
  include Util
17
17
  include Celluloid
18
18
 
19
+ exclusive :process
20
+
19
21
  def self.default_middleware
20
22
  Middleware::Chain.new do |m|
21
23
  m.add Middleware::Server::ExceptionHandler
@@ -30,19 +32,14 @@ module Sidekiq
30
32
  @boss = boss
31
33
  end
32
34
 
33
- def process(msg, queue)
35
+ def process(msgstr, queue)
36
+ msg = Sidekiq.load_json(msgstr)
34
37
  klass = constantize(msg['class'])
35
38
  worker = klass.new
36
39
 
37
- # Celluloid actor calls are performed within a Fiber.
38
- # This would give us a terribly small 4KB stack on MRI
39
- # so we use Celluloid's defer to run things in a thread pool
40
- # in order to get a full-sized stack for the Worker.
41
- defer do
42
- stats(worker, msg, queue) do
43
- Sidekiq.server_middleware.invoke(worker, msg, queue) do
44
- worker.perform(*msg['args'])
45
- end
40
+ stats(worker, msg, queue) do
41
+ Sidekiq.server_middleware.invoke(worker, msg, queue) do
42
+ worker.perform(*msg['args'])
46
43
  end
47
44
  end
48
45
  @boss.processor_done!(current_actor)
@@ -6,16 +6,17 @@ module Sidekiq
6
6
  class RedisConnection
7
7
  def self.create(options={})
8
8
  url = options[:url] || ENV['REDISTOGO_URL'] || 'redis://localhost:6379/0'
9
+ driver = options[:driver] || 'ruby'
9
10
  # need a connection for Fetcher and Retry
10
11
  size = options[:size] || (Sidekiq.server? ? (Sidekiq.options[:concurrency] + 2) : 5)
11
12
 
12
13
  ConnectionPool.new(:timeout => 1, :size => size) do
13
- build_client(url, options[:namespace])
14
+ build_client(url, options[:namespace], driver)
14
15
  end
15
16
  end
16
17
 
17
- def self.build_client(url, namespace)
18
- client = Redis.connect(:url => url)
18
+ def self.build_client(url, namespace, driver)
19
+ client = Redis.connect(:url => url, :driver => driver)
19
20
  if namespace
20
21
  Redis::Namespace.new(namespace, :redis => client)
21
22
  else
@@ -35,20 +35,27 @@ module Sidekiq
35
35
  messages.each do |message|
36
36
  logger.debug { "enqueued #{sorted_set}: #{message}" }
37
37
  msg = Sidekiq.load_json(message)
38
- conn.rpush("queue:#{msg['queue']}", message)
38
+ conn.multi do
39
+ conn.sadd('queues', msg['queue'])
40
+ conn.rpush("queue:#{msg['queue']}", message)
41
+ end
39
42
  end
40
43
  end
41
44
  end
42
45
 
43
- after(POLL_INTERVAL) { poll }
46
+ after(poll_interval) { poll }
44
47
  end
45
48
  end
46
49
 
47
50
  private
48
51
 
52
+ def poll_interval
53
+ Sidekiq.options[:poll_interval] || POLL_INTERVAL
54
+ end
55
+
49
56
  def add_jitter
50
57
  begin
51
- sleep(POLL_INTERVAL * rand)
58
+ sleep(poll_interval * rand)
52
59
  rescue Celluloid::Task::TerminatedError
53
60
  # Hit Ctrl-C when Sidekiq is finished booting and we have a chance
54
61
  # to get here.
@@ -24,22 +24,12 @@ module Sidekiq
24
24
  # assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size
25
25
  #
26
26
  module ClassMethods
27
- alias_method :perform_async_old, :perform_async
28
- def perform_async(*args)
29
- jobs << { 'class' => self.name, 'args' => args }
27
+ alias_method :client_push_old, :client_push
28
+ def client_push(opts)
29
+ jobs << opts
30
30
  true
31
31
  end
32
32
 
33
- alias_method :perform_in_old, :perform_in
34
- alias_method :perform_at_old, :perform_at
35
- def perform_in(interval, *args)
36
- int = interval.to_f
37
- ts = (int < 1_000_000_000 ? Time.now.to_f + int : int)
38
- jobs << { 'class' => self.name, 'args' => args, 'at' => ts }
39
- true
40
- end
41
- alias_method :perform_at, :perform_in
42
-
43
33
  def jobs
44
34
  @pushed ||= []
45
35
  end
@@ -1,3 +1,3 @@
1
1
  module Sidekiq
2
- VERSION = "2.0.3"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -1,6 +1,8 @@
1
1
  require 'sinatra/base'
2
2
  require 'slim'
3
3
  require 'sprockets'
4
+ require 'sidekiq/paginator'
5
+
4
6
  module Sidekiq
5
7
  class SprocketsMiddleware
6
8
  def initialize(app, options={})
@@ -28,6 +30,8 @@ module Sidekiq
28
30
  end
29
31
 
30
32
  class Web < Sinatra::Base
33
+ include Sidekiq::Paginator
34
+
31
35
  dir = File.expand_path(File.dirname(__FILE__) + "/../../web")
32
36
  set :views, "#{dir}/views"
33
37
  set :root, "#{dir}/public"
@@ -68,21 +72,6 @@ module Sidekiq
68
72
  Sidekiq.redis { |conn| conn.zcard(name) }
69
73
  end
70
74
 
71
- def retries(count=50)
72
- zcontents('retry', count)
73
- end
74
-
75
- def scheduled(count=50)
76
- zcontents('schedule', count)
77
- end
78
-
79
- def zcontents(name, count)
80
- Sidekiq.redis do |conn|
81
- results = conn.zrange(name, 0, count, :withscores => true)
82
- results.map { |msg, score| [Sidekiq.load_json(msg), score] }
83
- end
84
- end
85
-
86
75
  def queues
87
76
  @queues ||= Sidekiq.redis do |conn|
88
77
  conn.smembers('queues').map do |q|
@@ -135,9 +124,10 @@ module Sidekiq
135
124
 
136
125
  get "/queues/:name" do
137
126
  halt 404 unless params[:name]
138
- count = (params[:count] || 10).to_i
127
+ @count = (params[:count] || 25).to_i
139
128
  @name = params[:name]
140
- @messages = Sidekiq.redis {|conn| conn.lrange("queue:#{@name}", 0, count) }.map { |str| Sidekiq.load_json(str) }
129
+ (@current_page, @total_size, @messages) = page("queue:#{@name}", params[:page], @count)
130
+ @messages = @messages.map {|msg| Sidekiq.load_json(msg) }
141
131
  slim :queue
142
132
  end
143
133
 
@@ -163,12 +153,16 @@ module Sidekiq
163
153
  end
164
154
 
165
155
  get '/retries' do
166
- @retries = retries
156
+ @count = (params[:count] || 25).to_i
157
+ (@current_page, @total_size, @retries) = page("retry", params[:page], @count)
158
+ @retries = @retries.map {|msg, score| [Sidekiq.load_json(msg), score] }
167
159
  slim :retries
168
160
  end
169
161
 
170
162
  get '/scheduled' do
171
- @scheduled = scheduled
163
+ @count = (params[:count] || 25).to_i
164
+ (@current_page, @total_size, @scheduled) = page("schedule", params[:page], @count)
165
+ @scheduled = @scheduled.map {|msg, score| [Sidekiq.load_json(msg), score] }
172
166
  slim :scheduled
173
167
  end
174
168
 
@@ -32,13 +32,13 @@ module Sidekiq
32
32
 
33
33
  module ClassMethods
34
34
  def perform_async(*args)
35
- Sidekiq::Client.push('class' => self, 'args' => args)
35
+ client_push('class' => self, 'args' => args)
36
36
  end
37
37
 
38
38
  def perform_in(interval, *args)
39
39
  int = interval.to_f
40
40
  ts = (int < 1_000_000_000 ? Time.now.to_f + int : int)
41
- Sidekiq::Client.push('class' => self, 'args' => args, 'at' => ts)
41
+ client_push('class' => self, 'args' => args, 'at' => ts)
42
42
  end
43
43
  alias_method :perform_at, :perform_in
44
44
 
@@ -46,7 +46,6 @@ module Sidekiq
46
46
  # Allows customization for this type of Worker.
47
47
  # Legal options:
48
48
  #
49
- # :unique - enable the UniqueJobs middleware for this Worker, default *true*
50
49
  # :queue - use a named queue for this Worker, default 'default'
51
50
  # :retry - enable the RetryJobs middleware for this Worker, default *true*
52
51
  # :timeout - timeout the perform method after N seconds, default *nil*
@@ -56,7 +55,7 @@ module Sidekiq
56
55
  self.sidekiq_options_hash = get_sidekiq_options.merge(stringify_keys(opts || {}))
57
56
  end
58
57
 
59
- DEFAULT_OPTIONS = { 'unique' => true, 'retry' => true, 'queue' => 'default' }
58
+ DEFAULT_OPTIONS = { 'retry' => true, 'queue' => 'default' }
60
59
 
61
60
  def get_sidekiq_options # :nodoc:
62
61
  self.sidekiq_options_hash ||= DEFAULT_OPTIONS
@@ -68,6 +67,11 @@ module Sidekiq
68
67
  end
69
68
  hash
70
69
  end
70
+
71
+ def client_push(*args) # :nodoc:
72
+ Sidekiq::Client.push(*args)
73
+ end
74
+
71
75
  end
72
76
  end
73
77
  end
@@ -9,7 +9,7 @@ platforms :jruby do
9
9
  gem 'activerecord-jdbcsqlite3-adapter'
10
10
  end
11
11
 
12
- gem 'rails', '3.2.2'
12
+ gem 'rails', '3.2.6'
13
13
  gem 'sidekiq', :path => '..'
14
14
  gem 'capistrano'
15
15
 
@@ -16,8 +16,8 @@ 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.0'
20
- gem.add_dependency 'celluloid', '~> 0.11.0'
19
+ gem.add_dependency 'connection_pool', '~> 0.9.2'
20
+ gem.add_dependency 'celluloid', '~> 0.11.1'
21
21
  gem.add_dependency 'multi_json', '~> 1'
22
22
  gem.add_development_dependency 'minitest', '~> 3'
23
23
  gem.add_development_dependency 'sinatra'
@@ -3,36 +3,6 @@ require 'sidekiq/client'
3
3
  require 'sidekiq/worker'
4
4
 
5
5
  class TestClient < MiniTest::Unit::TestCase
6
- describe 'with real redis' do
7
- before do
8
- Sidekiq.redis = REDIS
9
- Sidekiq.redis {|c| c.flushdb }
10
- end
11
-
12
- class QueueWorker
13
- include Sidekiq::Worker
14
- sidekiq_options :queue => 'customqueue'
15
- end
16
-
17
- it 'does not push duplicate messages when configured for unique only' do
18
- Sidekiq.client_middleware do |chain|
19
- chain.add Sidekiq::Middleware::Client::UniqueJobs
20
- end
21
- QueueWorker.sidekiq_options :unique => true
22
- 10.times { Sidekiq::Client.push('class' => QueueWorker, 'args' => [1, 2]) }
23
- assert_equal 1, Sidekiq.redis {|c| c.llen("queue:customqueue") }
24
- end
25
-
26
- it 'does push duplicate messages when not configured for unique only' do
27
- Sidekiq.client_middleware do |chain|
28
- chain.add Sidekiq::Middleware::Client::UniqueJobs
29
- end
30
- QueueWorker.sidekiq_options :unique => false
31
- 10.times { Sidekiq::Client.push('class' => QueueWorker, 'args' => [1, 2]) }
32
- assert_equal 10, Sidekiq.redis {|c| c.llen("queue:customqueue") }
33
- end
34
- end
35
-
36
6
  describe 'with mock redis' do
37
7
  before do
38
8
  @redis = MiniTest::Mock.new
@@ -1,6 +1,5 @@
1
1
  require 'helper'
2
2
  require 'sidekiq/middleware/chain'
3
- require 'sidekiq/middleware/server/unique_jobs'
4
3
  require 'sidekiq/processor'
5
4
 
6
5
  class TestMiddleware < MiniTest::Unit::TestCase
@@ -43,9 +42,10 @@ class TestMiddleware < MiniTest::Unit::TestCase
43
42
  end
44
43
 
45
44
  class CustomWorker
45
+ $recorder = []
46
46
  include Sidekiq::Worker
47
47
  def perform(recorder)
48
- recorder << ['work_performed']
48
+ $recorder << ['work_performed']
49
49
  end
50
50
  end
51
51
 
@@ -56,18 +56,18 @@ class TestMiddleware < MiniTest::Unit::TestCase
56
56
 
57
57
  it 'executes middleware in the proper order' do
58
58
  recorder = []
59
- msg = { 'class' => CustomWorker.to_s, 'args' => [recorder] }
59
+ msg = Sidekiq.dump_json({ 'class' => CustomWorker.to_s, 'args' => [$recorder] })
60
60
 
61
61
  Sidekiq.server_middleware do |chain|
62
62
  # should only add once, second should be ignored
63
- 2.times { |i| chain.add CustomMiddleware, i.to_s, recorder }
63
+ 2.times { |i| chain.add CustomMiddleware, i.to_s, $recorder }
64
64
  end
65
65
 
66
66
  boss = MiniTest::Mock.new
67
67
  processor = Sidekiq::Processor.new(boss)
68
68
  boss.expect(:processor_done!, nil, [processor])
69
69
  processor.process(msg, 'default')
70
- assert_equal %w(0 before work_performed 0 after), recorder.flatten
70
+ assert_equal %w(0 before work_performed 0 after), $recorder.flatten
71
71
  end
72
72
 
73
73
  it 'allows middleware to abruptly stop processing rest of chain' do
@@ -20,7 +20,7 @@ class TestProcessor < MiniTest::Unit::TestCase
20
20
  end
21
21
 
22
22
  it 'processes as expected' do
23
- msg = { 'class' => MockWorker.to_s, 'args' => ['myarg'] }
23
+ msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
24
24
  processor = ::Sidekiq::Processor.new(@boss)
25
25
  @boss.expect(:processor_done!, nil, [processor])
26
26
  processor.process(msg, 'default')
@@ -113,7 +113,8 @@ class TestRetry < MiniTest::Unit::TestCase
113
113
  fake_msg = Sidekiq.dump_json({ 'class' => 'Bob', 'args' => [1,2], 'queue' => 'someq' })
114
114
  @redis.expect :multi, [[fake_msg], 1], []
115
115
  @redis.expect :multi, [[], nil], []
116
- @redis.expect :rpush, 1, ['queue:someq', fake_msg]
116
+ @redis.expect :multi, [[], nil], []
117
+ @redis.expect :multi, [[], nil], []
117
118
 
118
119
  inst = Sidekiq::Scheduled::Poller.new
119
120
  inst.poll
@@ -18,13 +18,13 @@ class TestScheduling < MiniTest::Unit::TestCase
18
18
  end
19
19
 
20
20
  it 'schedules a job via interval' do
21
- @redis.expect :zadd, 1, ['schedule', String, String]
21
+ @redis.expect :zadd, true, ['schedule', String, String]
22
22
  assert_equal true, ScheduledWorker.perform_in(600, 'mike')
23
23
  @redis.verify
24
24
  end
25
25
 
26
26
  it 'schedules a job via timestamp' do
27
- @redis.expect :zadd, 1, ['schedule', String, String]
27
+ @redis.expect :zadd, true, ['schedule', String, String]
28
28
  assert_equal true, ScheduledWorker.perform_in(5.days.from_now, 'mike')
29
29
  @redis.verify
30
30
  end
@@ -18,7 +18,7 @@ class TestStats < MiniTest::Unit::TestCase
18
18
  end
19
19
 
20
20
  it 'updates global stats in the success case' do
21
- msg = { 'class' => DumbWorker.to_s, 'args' => [""] }
21
+ msg = Sidekiq.dump_json({ 'class' => DumbWorker.to_s, 'args' => [""] })
22
22
  boss = MiniTest::Mock.new
23
23
 
24
24
  @redis.with do |conn|
@@ -44,7 +44,7 @@ class TestStats < MiniTest::Unit::TestCase
44
44
  end
45
45
 
46
46
  it 'updates global stats in the error case' do
47
- msg = { 'class' => DumbWorker.to_s, 'args' => [nil] }
47
+ msg = Sidekiq.dump_json({ 'class' => DumbWorker.to_s, 'args' => [nil] })
48
48
  boss = MiniTest::Mock.new
49
49
 
50
50
  @redis.with do |conn|
@@ -53,11 +53,9 @@ class TestTesting < MiniTest::Unit::TestCase
53
53
  after do
54
54
  # Undo override
55
55
  Sidekiq::Worker::ClassMethods.class_eval do
56
- %w(async at in).each do |token|
57
- remove_method :"perform_#{token}"
58
- alias_method :"perform_#{token}", :"perform_#{token}_old"
59
- remove_method :"perform_#{token}_old"
60
- end
56
+ remove_method :client_push
57
+ alias_method :client_push, :client_push_old
58
+ remove_method :client_push_old
61
59
  end
62
60
  end
63
61
 
@@ -0,0 +1,15 @@
1
+ - if @total_size > @count
2
+ .pagination.pagination-right
3
+ ul
4
+ li class="#{'disabled' if @current_page == 1}"
5
+ a href="#{url}?page=1" «
6
+ - if @current_page > 1
7
+ li
8
+ a href="#{url}?page=#{@current_page - 1}" #{@current_page - 1}
9
+ li.disabled
10
+ a href="#{url}?page=#{@current_page}" #{@current_page}
11
+ - if @total_size > @current_page * @count
12
+ li
13
+ a href="#{url}?page=#{@current_page + 1}" #{@current_page + 1}
14
+ li class="#{'disabled' if @total_size <= @current_page * @count}"
15
+ a href="#{url}?page=#{(@total_size / @count).ceil + 1}" »
@@ -1,5 +1,7 @@
1
1
  header
2
- h1 Latest messages in #{@name}
2
+ h1 Current messages in #{@name}
3
+
4
+ == slim :_paging, :locals => { :url => "#{root_path}queues/#{@name}" }
3
5
 
4
6
  table class="table table-striped table-bordered"
5
7
  tr
@@ -9,3 +11,5 @@ table class="table table-striped table-bordered"
9
11
  tr
10
12
  td= msg['class']
11
13
  td= msg['args'].inspect[0..100]
14
+
15
+ == slim :_paging, :locals => { :url => "#{root_path}queues/#{@name}" }
@@ -1,6 +1,8 @@
1
1
  h1 Retries
2
2
 
3
3
  - if @retries.size > 0
4
+ == slim :_paging, :locals => { :url => "#{root_path}retries" }
5
+
4
6
  form action="#{root_path}retries" method="post"
5
7
  table class="table table-striped table-bordered"
6
8
  tr
@@ -1,6 +1,8 @@
1
1
  h1 Scheduled Jobs
2
2
 
3
3
  - if @scheduled.size > 0
4
+ == slim :_paging, :locals => { :url => "#{root_path}scheduled" }
5
+
4
6
  form action="#{root_path}scheduled" method="post"
5
7
  table class="table table-striped table-bordered"
6
8
  tr
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.0.3
4
+ version: 2.1.0
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-06-20 00:00:00.000000000 Z
12
+ date: 2012-07-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
16
- requirement: &70268588228240 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '3'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70268588228240
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: redis-namespace
27
- requirement: &70268588227780 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,32 +37,47 @@ dependencies:
32
37
  version: '0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *70268588227780
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: connection_pool
38
- requirement: &70268588227180 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ~>
42
52
  - !ruby/object:Gem::Version
43
- version: 0.9.0
53
+ version: 0.9.2
44
54
  type: :runtime
45
55
  prerelease: false
46
- version_requirements: *70268588227180
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: celluloid
49
- requirement: &70268588226500 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ~>
53
68
  - !ruby/object:Gem::Version
54
- version: 0.11.0
69
+ version: 0.11.1
55
70
  type: :runtime
56
71
  prerelease: false
57
- version_requirements: *70268588226500
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.11.1
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: multi_json
60
- requirement: &70268588225840 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ~>
@@ -65,10 +85,15 @@ dependencies:
65
85
  version: '1'
66
86
  type: :runtime
67
87
  prerelease: false
68
- version_requirements: *70268588225840
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '1'
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: minitest
71
- requirement: &70268588225120 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
72
97
  none: false
73
98
  requirements:
74
99
  - - ~>
@@ -76,10 +101,15 @@ dependencies:
76
101
  version: '3'
77
102
  type: :development
78
103
  prerelease: false
79
- version_requirements: *70268588225120
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '3'
80
110
  - !ruby/object:Gem::Dependency
81
111
  name: sinatra
82
- requirement: &70268588224740 !ruby/object:Gem::Requirement
112
+ requirement: !ruby/object:Gem::Requirement
83
113
  none: false
84
114
  requirements:
85
115
  - - ! '>='
@@ -87,10 +117,15 @@ dependencies:
87
117
  version: '0'
88
118
  type: :development
89
119
  prerelease: false
90
- version_requirements: *70268588224740
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
91
126
  - !ruby/object:Gem::Dependency
92
127
  name: slim
93
- requirement: &70268588224280 !ruby/object:Gem::Requirement
128
+ requirement: !ruby/object:Gem::Requirement
94
129
  none: false
95
130
  requirements:
96
131
  - - ! '>='
@@ -98,10 +133,15 @@ dependencies:
98
133
  version: '0'
99
134
  type: :development
100
135
  prerelease: false
101
- version_requirements: *70268588224280
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
102
142
  - !ruby/object:Gem::Dependency
103
143
  name: rake
104
- requirement: &70268588223740 !ruby/object:Gem::Requirement
144
+ requirement: !ruby/object:Gem::Requirement
105
145
  none: false
106
146
  requirements:
107
147
  - - ! '>='
@@ -109,10 +149,15 @@ dependencies:
109
149
  version: '0'
110
150
  type: :development
111
151
  prerelease: false
112
- version_requirements: *70268588223740
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
113
158
  - !ruby/object:Gem::Dependency
114
159
  name: actionmailer
115
- requirement: &70268588223240 !ruby/object:Gem::Requirement
160
+ requirement: !ruby/object:Gem::Requirement
116
161
  none: false
117
162
  requirements:
118
163
  - - ~>
@@ -120,10 +165,15 @@ dependencies:
120
165
  version: '3'
121
166
  type: :development
122
167
  prerelease: false
123
- version_requirements: *70268588223240
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ~>
172
+ - !ruby/object:Gem::Version
173
+ version: '3'
124
174
  - !ruby/object:Gem::Dependency
125
175
  name: activerecord
126
- requirement: &70268588222720 !ruby/object:Gem::Requirement
176
+ requirement: !ruby/object:Gem::Requirement
127
177
  none: false
128
178
  requirements:
129
179
  - - ~>
@@ -131,7 +181,12 @@ dependencies:
131
181
  version: '3'
132
182
  type: :development
133
183
  prerelease: false
134
- version_requirements: *70268588222720
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ~>
188
+ - !ruby/object:Gem::Version
189
+ version: '3'
135
190
  description: Simple, efficient message processing for Ruby
136
191
  email:
137
192
  - mperham@gmail.com
@@ -143,6 +198,7 @@ extra_rdoc_files: []
143
198
  files:
144
199
  - .gitignore
145
200
  - .rvmrc
201
+ - .travis.yml
146
202
  - COMM-LICENSE
147
203
  - Changes.md
148
204
  - Gemfile
@@ -177,14 +233,12 @@ files:
177
233
  - lib/sidekiq/logging.rb
178
234
  - lib/sidekiq/manager.rb
179
235
  - lib/sidekiq/middleware/chain.rb
180
- - lib/sidekiq/middleware/client/unique_jobs.rb
181
236
  - lib/sidekiq/middleware/server/active_record.rb
182
237
  - lib/sidekiq/middleware/server/exception_handler.rb
183
- - lib/sidekiq/middleware/server/failure_jobs.rb
184
238
  - lib/sidekiq/middleware/server/logging.rb
185
239
  - lib/sidekiq/middleware/server/retry_jobs.rb
186
240
  - lib/sidekiq/middleware/server/timeout.rb
187
- - lib/sidekiq/middleware/server/unique_jobs.rb
241
+ - lib/sidekiq/paginator.rb
188
242
  - lib/sidekiq/processor.rb
189
243
  - lib/sidekiq/rails.rb
190
244
  - lib/sidekiq/redis_connection.rb
@@ -273,6 +327,7 @@ files:
273
327
  - web/assets/stylesheets/layout.css
274
328
  - web/assets/stylesheets/vendor/bootstrap-responsive.css
275
329
  - web/assets/stylesheets/vendor/bootstrap.css
330
+ - web/views/_paging.slim
276
331
  - web/views/index.slim
277
332
  - web/views/layout.slim
278
333
  - web/views/queue.slim
@@ -301,7 +356,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
301
356
  version: '0'
302
357
  requirements: []
303
358
  rubyforge_project:
304
- rubygems_version: 1.8.15
359
+ rubygems_version: 1.8.24
305
360
  signing_key:
306
361
  specification_version: 3
307
362
  summary: Simple, efficient message processing for Ruby
@@ -1,35 +0,0 @@
1
- require 'digest'
2
-
3
- module Sidekiq
4
- module Middleware
5
- module Client
6
- class UniqueJobs
7
- HASH_KEY_EXPIRATION = 30 * 60
8
-
9
- def call(worker_class, item, queue)
10
- enabled = worker_class.get_sidekiq_options['unique']
11
- if enabled
12
- payload_hash = Digest::MD5.hexdigest(Sidekiq.dump_json(item))
13
- unique = false
14
-
15
- Sidekiq.redis do |conn|
16
- conn.watch(payload_hash)
17
-
18
- if conn.get(payload_hash)
19
- conn.unwatch
20
- else
21
- unique = conn.multi do
22
- conn.setex(payload_hash, HASH_KEY_EXPIRATION, 1)
23
- end
24
- end
25
- end
26
- yield if unique
27
- else
28
- yield
29
- end
30
- end
31
-
32
- end
33
- end
34
- end
35
- end
@@ -1,23 +0,0 @@
1
- module Sidekiq
2
- module Middleware
3
- module Server
4
- class FailureJobs
5
- def call(*args)
6
- yield
7
- rescue => e
8
- data = {
9
- :failed_at => Time.now.strftime("%Y/%m/%d %H:%M:%S %Z"),
10
- :payload => args[1],
11
- :exception => e.class.to_s,
12
- :error => e.to_s,
13
- :backtrace => e.backtrace,
14
- :worker => args[1]['class'],
15
- :queue => args[2]
16
- }
17
- Sidekiq.redis {|conn| conn.rpush(:failed, Sidekiq.dump_json(data)) }
18
- raise
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,15 +0,0 @@
1
- module Sidekiq
2
- module Middleware
3
- module Server
4
- class UniqueJobs
5
- def call(*args)
6
- yield
7
- ensure
8
- json = Sidekiq.dump_json(args[1])
9
- hash = Digest::MD5.hexdigest(json)
10
- Sidekiq.redis {|conn| conn.del(hash) }
11
- end
12
- end
13
- end
14
- end
15
- end