sidekiq 0.5.1 → 0.6.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/.gitignore +5 -0
- data/.rvmrc +2 -1
- data/Changes.md +11 -0
- data/LICENSE +11 -4
- data/README.md +1 -7
- data/TODO.md +0 -1
- data/bin/sidekiq +2 -0
- data/examples/por.rb +17 -0
- data/examples/sinkiq.rb +57 -0
- data/lib/sidekiq.rb +1 -1
- data/lib/sidekiq/cli.rb +72 -34
- data/lib/sidekiq/client.rb +33 -16
- data/lib/sidekiq/manager.rb +37 -47
- data/lib/sidekiq/middleware/chain.rb +92 -0
- data/lib/sidekiq/middleware/client/resque_web_compatibility.rb +17 -0
- data/lib/sidekiq/middleware/client/unique_jobs.rb +30 -0
- data/lib/sidekiq/middleware/server/active_record.rb +13 -0
- data/lib/sidekiq/middleware/server/airbrake.rb +30 -0
- data/lib/sidekiq/middleware/server/unique_jobs.rb +17 -0
- data/lib/sidekiq/processor.rb +74 -16
- data/lib/sidekiq/redis_connection.rb +23 -0
- data/lib/sidekiq/testing.rb +34 -0
- data/lib/sidekiq/util.rb +21 -12
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/worker.rb +6 -7
- data/myapp/Gemfile +4 -1
- data/myapp/Gemfile.lock +29 -6
- data/myapp/app/controllers/work_controller.rb +9 -0
- data/myapp/app/views/work/index.html.erb +1 -0
- data/myapp/app/workers/hard_worker.rb +4 -2
- data/myapp/config/environments/development.rb +1 -0
- data/myapp/config/initializers/sidekiq.rb +1 -0
- data/myapp/config/routes.rb +4 -56
- data/sidekiq.gemspec +1 -0
- data/test/fake_env.rb +0 -0
- data/test/helper.rb +3 -0
- data/test/test_cli.rb +49 -0
- data/test/test_client.rb +52 -10
- data/test/test_manager.rb +11 -6
- data/test/test_middleware.rb +39 -20
- data/test/test_processor.rb +3 -2
- data/test/test_stats.rb +79 -0
- data/test/test_testing.rb +32 -0
- metadata +47 -18
- data/Gemfile.lock +0 -32
- data/lib/sidekiq/middleware.rb +0 -89
- data/test/timed_queue.rb +0 -42
data/myapp/Gemfile
CHANGED
data/myapp/Gemfile.lock
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
sidekiq (0.6.0)
|
5
|
+
celluloid
|
6
|
+
connection_pool
|
7
|
+
multi_json
|
8
|
+
redis
|
9
|
+
redis-namespace
|
10
|
+
|
1
11
|
GEM
|
2
12
|
remote: https://rubygems.org/
|
3
13
|
specs:
|
@@ -37,6 +47,7 @@ GEM
|
|
37
47
|
i18n (0.6.0)
|
38
48
|
journey (1.0.1)
|
39
49
|
json (1.6.5)
|
50
|
+
json (1.6.5-java)
|
40
51
|
mail (2.4.1)
|
41
52
|
i18n (>= 0.4.0)
|
42
53
|
mime-types (~> 1.16)
|
@@ -47,6 +58,8 @@ GEM
|
|
47
58
|
rack (1.4.1)
|
48
59
|
rack-cache (1.1)
|
49
60
|
rack (>= 0.4)
|
61
|
+
rack-protection (1.2.0)
|
62
|
+
rack
|
50
63
|
rack-ssl (1.3.2)
|
51
64
|
rack
|
52
65
|
rack-test (0.6.1)
|
@@ -70,11 +83,17 @@ GEM
|
|
70
83
|
rdoc (3.12)
|
71
84
|
json (~> 1.4)
|
72
85
|
redis (2.2.2)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
multi_json
|
77
|
-
redis
|
86
|
+
redis-namespace (1.0.3)
|
87
|
+
redis (< 3.0.0)
|
88
|
+
resque (1.19.0)
|
89
|
+
multi_json (~> 1.0)
|
90
|
+
redis-namespace (~> 1.0.2)
|
91
|
+
sinatra (>= 0.9.2)
|
92
|
+
vegas (~> 0.1.2)
|
93
|
+
sinatra (1.3.2)
|
94
|
+
rack (~> 1.3, >= 1.3.6)
|
95
|
+
rack-protection (~> 1.2)
|
96
|
+
tilt (~> 1.3, >= 1.3.3)
|
78
97
|
sprockets (2.1.2)
|
79
98
|
hike (~> 1.2)
|
80
99
|
rack (~> 1.0)
|
@@ -86,11 +105,15 @@ GEM
|
|
86
105
|
polyglot
|
87
106
|
polyglot (>= 0.3.1)
|
88
107
|
tzinfo (0.3.31)
|
108
|
+
vegas (0.1.11)
|
109
|
+
rack (>= 1.0.0)
|
89
110
|
|
90
111
|
PLATFORMS
|
112
|
+
java
|
91
113
|
ruby
|
92
114
|
|
93
115
|
DEPENDENCIES
|
94
116
|
rails (= 3.2.1)
|
95
|
-
|
117
|
+
resque
|
118
|
+
sidekiq!
|
96
119
|
sqlite3
|
@@ -0,0 +1 @@
|
|
1
|
+
Added <%= @count %> jobs!
|
@@ -0,0 +1 @@
|
|
1
|
+
Sidekiq::Client.redis = Sidekiq::RedisConnection.create(:namespace => 'resque')
|
data/myapp/config/routes.rb
CHANGED
@@ -1,58 +1,6 @@
|
|
1
|
-
|
2
|
-
# The priority is based upon order of creation:
|
3
|
-
# first created -> highest priority.
|
4
|
-
|
5
|
-
# Sample of regular route:
|
6
|
-
# match 'products/:id' => 'catalog#view'
|
7
|
-
# Keep in mind you can assign values other than :controller and :action
|
8
|
-
|
9
|
-
# Sample of named route:
|
10
|
-
# match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
|
11
|
-
# This route can be invoked with purchase_url(:id => product.id)
|
12
|
-
|
13
|
-
# Sample resource route (maps HTTP verbs to controller actions automatically):
|
14
|
-
# resources :products
|
15
|
-
|
16
|
-
# Sample resource route with options:
|
17
|
-
# resources :products do
|
18
|
-
# member do
|
19
|
-
# get 'short'
|
20
|
-
# post 'toggle'
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# collection do
|
24
|
-
# get 'sold'
|
25
|
-
# end
|
26
|
-
# end
|
27
|
-
|
28
|
-
# Sample resource route with sub-resources:
|
29
|
-
# resources :products do
|
30
|
-
# resources :comments, :sales
|
31
|
-
# resource :seller
|
32
|
-
# end
|
1
|
+
require 'resque/server'
|
33
2
|
|
34
|
-
|
35
|
-
|
36
|
-
#
|
37
|
-
# resources :sales do
|
38
|
-
# get 'recent', :on => :collection
|
39
|
-
# end
|
40
|
-
# end
|
41
|
-
|
42
|
-
# Sample resource route within a namespace:
|
43
|
-
# namespace :admin do
|
44
|
-
# # Directs /admin/products/* to Admin::ProductsController
|
45
|
-
# # (app/controllers/admin/products_controller.rb)
|
46
|
-
# resources :products
|
47
|
-
# end
|
48
|
-
|
49
|
-
# You can have the root of your site routed with "root"
|
50
|
-
# just remember to delete public/index.html.
|
51
|
-
# root :to => 'welcome#index'
|
52
|
-
|
53
|
-
# See how all your routes lay out with "rake routes"
|
54
|
-
|
55
|
-
# This is a legacy wild controller route that's not recommended for RESTful applications.
|
56
|
-
# Note: This route will make all actions in every controller accessible via GET requests.
|
57
|
-
# match ':controller(/:action(/:id))(.:format)'
|
3
|
+
Myapp::Application.routes.draw do
|
4
|
+
mount Resque::Server.new, :at => '/resque'
|
5
|
+
get "work" => "work#index"
|
58
6
|
end
|
data/sidekiq.gemspec
CHANGED
@@ -14,6 +14,7 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.require_paths = ["lib"]
|
15
15
|
gem.version = Sidekiq::VERSION
|
16
16
|
gem.add_dependency 'redis'
|
17
|
+
gem.add_dependency 'redis-namespace'
|
17
18
|
gem.add_dependency 'connection_pool'
|
18
19
|
gem.add_dependency 'celluloid'
|
19
20
|
gem.add_dependency 'multi_json'
|
data/test/fake_env.rb
ADDED
File without changes
|
data/test/helper.rb
CHANGED
data/test/test_cli.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'sidekiq/cli'
|
3
|
+
|
4
|
+
class TestCli < MiniTest::Unit::TestCase
|
5
|
+
describe 'with cli' do
|
6
|
+
before do
|
7
|
+
@cli = new_cli
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'blows up with an invalid require' do
|
11
|
+
assert_raises ArgumentError do
|
12
|
+
@cli.parse(['sidekiq', '-r', 'foobar'])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'blows up with invalid Ruby' do
|
17
|
+
@cli.parse(['sidekiq', '-r', './test/fake_env.rb'])
|
18
|
+
assert($LOADED_FEATURES.any? { |x| x =~ /fake_env/ })
|
19
|
+
assert @cli.valid?
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'changes concurrency' do
|
23
|
+
@cli.parse(['sidekiq', '-c', '60', '-r', './test/fake_env.rb'])
|
24
|
+
assert_equal 60, @cli.options[:processor_count]
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'changes queues' do
|
28
|
+
@cli.parse(['sidekiq', '-q', 'foo', '-r', './test/fake_env.rb'])
|
29
|
+
assert_equal ['foo'], @cli.options[:queues]
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'handles weights' do
|
33
|
+
@cli.parse(['sidekiq', '-q', 'foo,3', '-q', 'bar', '-r', './test/fake_env.rb'])
|
34
|
+
assert_equal %w(bar foo foo foo), @cli.options[:queues].sort
|
35
|
+
end
|
36
|
+
|
37
|
+
def new_cli
|
38
|
+
cli = Sidekiq::CLI.new
|
39
|
+
def cli.die(code)
|
40
|
+
@code = code
|
41
|
+
end
|
42
|
+
|
43
|
+
def cli.valid?
|
44
|
+
!@code
|
45
|
+
end
|
46
|
+
cli
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/test/test_client.rb
CHANGED
@@ -3,9 +3,41 @@ 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::Client.redis = Redis.connect(:url => 'redis://localhost/sidekiq_test')
|
9
|
+
Sidekiq::Client.redis.flushdb
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'does not push duplicate messages when configured for unique only' do
|
13
|
+
Sidekiq::Client.middleware.entries.clear
|
14
|
+
Sidekiq::Client.middleware.register do
|
15
|
+
use Sidekiq::Middleware::Client::UniqueJobs, Sidekiq::Client.redis
|
16
|
+
use Sidekiq::Middleware::Client::ResqueWebCompatibility, Sidekiq::Client.redis
|
17
|
+
end
|
18
|
+
10.times { Sidekiq::Client.push('customqueue', 'class' => 'Foo', 'args' => [1, 2]) }
|
19
|
+
assert_equal 1, Sidekiq::Client.redis.llen("queue:customqueue")
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'does push duplicate messages when not configured for unique only' do
|
23
|
+
Sidekiq::Client.middleware.unregister(Sidekiq::Middleware::Client::UniqueJobs)
|
24
|
+
10.times { Sidekiq::Client.push('customqueue2', 'class' => 'Foo', 'args' => [1, 2]) }
|
25
|
+
assert_equal 10, Sidekiq::Client.redis.llen("queue:customqueue2")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
6
29
|
describe 'with mock redis' do
|
7
30
|
before do
|
8
31
|
@redis = MiniTest::Mock.new
|
32
|
+
def @redis.multi; yield; end
|
33
|
+
def @redis.set(*); true; end
|
34
|
+
def @redis.sadd(*); true; end
|
35
|
+
def @redis.srem(*); true; end
|
36
|
+
def @redis.get(*); nil; end
|
37
|
+
def @redis.del(*); nil; end
|
38
|
+
def @redis.incrby(*); nil; end
|
39
|
+
def @redis.setex(*); nil; end
|
40
|
+
def @redis.expire(*); true; end
|
9
41
|
Sidekiq::Client.redis = @redis
|
10
42
|
end
|
11
43
|
|
@@ -21,29 +53,39 @@ class TestClient < MiniTest::Unit::TestCase
|
|
21
53
|
|
22
54
|
it 'pushes messages to redis' do
|
23
55
|
@redis.expect :rpush, 1, ['queue:foo', String]
|
24
|
-
|
25
|
-
assert
|
56
|
+
pushed = Sidekiq::Client.push('foo', 'class' => 'Foo', 'args' => [1, 2])
|
57
|
+
assert pushed
|
26
58
|
@redis.verify
|
27
59
|
end
|
28
60
|
|
29
61
|
class MyWorker
|
30
62
|
include Sidekiq::Worker
|
31
|
-
def self.queue
|
32
|
-
'foo'
|
33
|
-
end
|
34
63
|
end
|
35
64
|
|
36
65
|
it 'handles perform_async' do
|
37
66
|
@redis.expect :rpush, 1, ['queue:default', String]
|
38
|
-
|
39
|
-
assert
|
67
|
+
pushed = MyWorker.perform_async(1, 2)
|
68
|
+
assert pushed
|
40
69
|
@redis.verify
|
41
70
|
end
|
42
71
|
|
43
72
|
it 'enqueues messages to redis' do
|
44
|
-
@redis.expect :rpush, 1, ['queue:
|
45
|
-
|
46
|
-
assert
|
73
|
+
@redis.expect :rpush, 1, ['queue:default', String]
|
74
|
+
pushed = Sidekiq::Client.enqueue(MyWorker, 1, 2)
|
75
|
+
assert pushed
|
76
|
+
@redis.verify
|
77
|
+
end
|
78
|
+
|
79
|
+
class QueuedWorker
|
80
|
+
include Sidekiq::Worker
|
81
|
+
|
82
|
+
queue :flimflam
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'enqueues to the named queue' do
|
86
|
+
@redis.expect :rpush, 1, ['queue:flimflam', String]
|
87
|
+
pushed = QueuedWorker.perform_async(1, 2)
|
88
|
+
assert pushed
|
47
89
|
@redis.verify
|
48
90
|
end
|
49
91
|
end
|
data/test/test_manager.rb
CHANGED
@@ -1,36 +1,41 @@
|
|
1
1
|
require 'helper'
|
2
2
|
require 'sidekiq'
|
3
3
|
require 'sidekiq/manager'
|
4
|
-
|
4
|
+
|
5
|
+
# for TimedQueue
|
6
|
+
require 'connection_pool'
|
5
7
|
|
6
8
|
class TestManager < MiniTest::Unit::TestCase
|
7
9
|
describe 'with redis' do
|
8
10
|
before do
|
9
|
-
Sidekiq::Client.redis = @redis =
|
11
|
+
Sidekiq::Manager.redis = Sidekiq::Client.redis = @redis = Sidekiq::RedisConnection.create(:url => 'redis://localhost/sidekiq_test')
|
10
12
|
@redis.flushdb
|
11
13
|
$processed = 0
|
14
|
+
$mutex = Mutex.new
|
12
15
|
end
|
13
16
|
|
14
17
|
class IntegrationWorker
|
15
18
|
include Sidekiq::Worker
|
16
19
|
|
17
20
|
def perform(a, b)
|
18
|
-
$
|
21
|
+
$mutex.synchronize do
|
22
|
+
$processed += 1
|
23
|
+
end
|
19
24
|
a + b
|
20
25
|
end
|
21
26
|
end
|
22
27
|
|
23
28
|
it 'processes messages' do
|
24
29
|
Sidekiq::Client.push(:foo, 'class' => IntegrationWorker, 'args' => [1, 2])
|
25
|
-
Sidekiq::Client.push(:foo, 'class' => IntegrationWorker, 'args' => [1,
|
30
|
+
Sidekiq::Client.push(:foo, 'class' => IntegrationWorker, 'args' => [1, 3])
|
26
31
|
|
27
32
|
q = TimedQueue.new
|
28
|
-
mgr = Sidekiq::Manager.new(
|
33
|
+
mgr = Sidekiq::Manager.new(:queues => [:foo], :processor_count => 2)
|
29
34
|
mgr.when_done do |_|
|
30
35
|
q << 'done' if $processed == 2
|
31
36
|
end
|
32
37
|
mgr.start!
|
33
|
-
result = q.timed_pop
|
38
|
+
result = q.timed_pop(1.0)
|
34
39
|
assert_equal 'done', result
|
35
40
|
mgr.stop
|
36
41
|
end
|
data/test/test_middleware.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'helper'
|
2
|
-
require 'sidekiq/middleware'
|
2
|
+
require 'sidekiq/middleware/chain'
|
3
|
+
require 'sidekiq/middleware/server/unique_jobs'
|
3
4
|
require 'sidekiq/processor'
|
4
5
|
|
5
6
|
class TestMiddleware < MiniTest::Unit::TestCase
|
6
7
|
describe 'middleware chain' do
|
7
8
|
before do
|
8
|
-
@
|
9
|
-
|
9
|
+
Sidekiq::Manager.redis = @redis = Sidekiq::RedisConnection.create(:url => 'redis://localhost/sidekiq_test')
|
10
|
+
Sidekiq::Client.redis = nil
|
10
11
|
end
|
11
12
|
|
12
13
|
class CustomMiddleware
|
@@ -15,48 +16,66 @@ class TestMiddleware < MiniTest::Unit::TestCase
|
|
15
16
|
@recorder = recorder
|
16
17
|
end
|
17
18
|
|
18
|
-
def call(
|
19
|
+
def call(*args)
|
19
20
|
@recorder << [@name, 'before']
|
20
21
|
yield
|
21
22
|
@recorder << [@name, 'after']
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
|
-
it 'configures default middleware' do
|
26
|
-
chain = Sidekiq::Middleware::Chain.chain
|
27
|
-
assert_equal chain, Sidekiq::Middleware::Chain.default
|
28
|
-
end
|
29
|
-
|
30
26
|
it 'supports custom middleware' do
|
31
|
-
Sidekiq::Middleware::Chain.
|
27
|
+
chain = Sidekiq::Middleware::Chain.new
|
28
|
+
chain.register do
|
32
29
|
use CustomMiddleware, 1, []
|
33
30
|
end
|
34
|
-
|
35
|
-
assert_equal chain.last.klass
|
31
|
+
|
32
|
+
assert_equal CustomMiddleware, chain.entries.last.klass
|
36
33
|
end
|
37
34
|
|
38
35
|
class CustomWorker
|
36
|
+
include Sidekiq::Worker
|
39
37
|
def perform(recorder)
|
40
38
|
recorder << ['work_performed']
|
41
39
|
end
|
42
40
|
end
|
43
41
|
|
42
|
+
class NonYieldingMiddleware
|
43
|
+
def call(*args)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
44
47
|
it 'executes middleware in the proper order' do
|
48
|
+
Sidekiq::Middleware::Server::UniqueJobs.class_eval do
|
49
|
+
def call(*args); yield; end
|
50
|
+
end
|
51
|
+
|
45
52
|
recorder = []
|
46
53
|
msg = { 'class' => CustomWorker.to_s, 'args' => [recorder] }
|
47
54
|
|
48
|
-
Sidekiq::
|
55
|
+
Sidekiq::Processor.middleware.register do
|
49
56
|
2.times { |i| use CustomMiddleware, i.to_s, recorder }
|
50
57
|
end
|
51
58
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
59
|
+
boss = MiniTest::Mock.new
|
60
|
+
processor = Sidekiq::Processor.new(boss)
|
61
|
+
boss.expect(:processor_done!, nil, [processor])
|
62
|
+
processor.process(msg, 'default')
|
63
|
+
assert_equal %w(0 before work_performed 0 after), recorder.flatten
|
56
64
|
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
65
|
|
66
|
+
it 'allows middleware to abruptly stop processing rest of chain' do
|
67
|
+
recorder = []
|
68
|
+
chain = Sidekiq::Middleware::Chain.new
|
61
69
|
|
70
|
+
chain.register do
|
71
|
+
use NonYieldingMiddleware
|
72
|
+
use CustomMiddleware, 1, recorder
|
73
|
+
end
|
62
74
|
|
75
|
+
final_action = nil
|
76
|
+
chain.invoke { final_action = true }
|
77
|
+
assert_equal nil, final_action
|
78
|
+
assert_equal [], recorder
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|