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.
- data/.travis.yml +15 -0
- data/Changes.md +13 -2
- data/Gemfile +2 -1
- data/README.md +2 -2
- data/examples/chef/cookbooks/sidekiq/templates/default/sidekiq.erb +2 -41
- data/lib/sidekiq.rb +8 -0
- data/lib/sidekiq/cli.rb +2 -2
- data/lib/sidekiq/client.rb +1 -2
- data/lib/sidekiq/extensions/generic_proxy.rb +1 -1
- data/lib/sidekiq/manager.rb +1 -1
- data/lib/sidekiq/middleware/chain.rb +11 -7
- data/lib/sidekiq/paginator.rb +31 -0
- data/lib/sidekiq/processor.rb +7 -10
- data/lib/sidekiq/redis_connection.rb +4 -3
- data/lib/sidekiq/scheduled.rb +10 -3
- data/lib/sidekiq/testing.rb +3 -13
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +13 -19
- data/lib/sidekiq/worker.rb +8 -4
- data/myapp/Gemfile +1 -1
- data/sidekiq.gemspec +2 -2
- data/test/test_client.rb +0 -30
- data/test/test_middleware.rb +5 -5
- data/test/test_processor.rb +1 -1
- data/test/test_retry.rb +2 -1
- data/test/test_scheduling.rb +2 -2
- data/test/test_stats.rb +2 -2
- data/test/test_testing.rb +3 -5
- data/web/views/_paging.slim +15 -0
- data/web/views/queue.slim +5 -1
- data/web/views/retries.slim +2 -0
- data/web/views/scheduled.slim +2 -0
- metadata +85 -30
- data/lib/sidekiq/middleware/client/unique_jobs.rb +0 -35
- data/lib/sidekiq/middleware/server/failure_jobs.rb +0 -23
- data/lib/sidekiq/middleware/server/unique_jobs.rb +0 -15
data/.travis.yml
ADDED
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
|
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
|
-
-
|
20
|
+
- Sidekiq has a new mailing list: sidekiq@librelist.org See README.
|
10
21
|
|
11
22
|
2.0.2
|
12
23
|
-----------
|
data/Gemfile
CHANGED
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
|
-
|
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/.
|
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="
|
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
|
data/lib/sidekiq.rb
CHANGED
data/lib/sidekiq/cli.rb
CHANGED
@@ -17,8 +17,8 @@ end
|
|
17
17
|
|
18
18
|
trap 'TTIN' do
|
19
19
|
Thread.list.each do |thread|
|
20
|
-
|
21
|
-
|
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
|
|
data/lib/sidekiq/client.rb
CHANGED
@@ -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 =
|
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)
|
data/lib/sidekiq/manager.rb
CHANGED
@@ -7,22 +7,26 @@ module Sidekiq
|
|
7
7
|
#
|
8
8
|
# To add middleware for the client:
|
9
9
|
#
|
10
|
-
# Sidekiq.
|
11
|
-
#
|
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.
|
18
|
-
#
|
19
|
-
#
|
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(
|
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
|
data/lib/sidekiq/processor.rb
CHANGED
@@ -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(
|
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
|
-
|
38
|
-
|
39
|
-
|
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
|
data/lib/sidekiq/scheduled.rb
CHANGED
@@ -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.
|
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(
|
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(
|
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.
|
data/lib/sidekiq/testing.rb
CHANGED
@@ -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 :
|
28
|
-
def
|
29
|
-
jobs <<
|
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
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web.rb
CHANGED
@@ -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] ||
|
127
|
+
@count = (params[:count] || 25).to_i
|
139
128
|
@name = params[:name]
|
140
|
-
@messages =
|
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
|
-
@
|
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
|
-
@
|
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
|
|
data/lib/sidekiq/worker.rb
CHANGED
@@ -32,13 +32,13 @@ module Sidekiq
|
|
32
32
|
|
33
33
|
module ClassMethods
|
34
34
|
def perform_async(*args)
|
35
|
-
|
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
|
-
|
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 = { '
|
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
|
data/myapp/Gemfile
CHANGED
data/sidekiq.gemspec
CHANGED
@@ -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.
|
20
|
-
gem.add_dependency 'celluloid', '~> 0.11.
|
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'
|
data/test/test_client.rb
CHANGED
@@ -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
|
data/test/test_middleware.rb
CHANGED
@@ -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
|
data/test/test_processor.rb
CHANGED
@@ -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')
|
data/test/test_retry.rb
CHANGED
@@ -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 :
|
116
|
+
@redis.expect :multi, [[], nil], []
|
117
|
+
@redis.expect :multi, [[], nil], []
|
117
118
|
|
118
119
|
inst = Sidekiq::Scheduled::Poller.new
|
119
120
|
inst.poll
|
data/test/test_scheduling.rb
CHANGED
@@ -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,
|
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,
|
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
|
data/test/test_stats.rb
CHANGED
@@ -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|
|
data/test/test_testing.rb
CHANGED
@@ -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
|
-
|
57
|
-
|
58
|
-
|
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}" »
|
data/web/views/queue.slim
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
header
|
2
|
-
h1
|
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}" }
|
data/web/views/retries.slim
CHANGED
data/web/views/scheduled.slim
CHANGED
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
|
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-
|
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:
|
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:
|
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:
|
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:
|
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:
|
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.
|
53
|
+
version: 0.9.2
|
44
54
|
type: :runtime
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
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:
|
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.
|
69
|
+
version: 0.11.1
|
55
70
|
type: :runtime
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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/
|
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.
|
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
|