sidekiq 0.6.0 → 0.7.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 +3 -0
- data/Changes.md +15 -0
- data/README.md +1 -1
- data/TODO.md +0 -2
- data/examples/chef/cookbooks/sidekiq/README.rdoc +7 -0
- data/examples/chef/cookbooks/sidekiq/recipes/default.rb +54 -0
- data/examples/chef/cookbooks/sidekiq/templates/default/monitrc.conf.erb +8 -0
- data/examples/chef/cookbooks/sidekiq/templates/default/sidekiq.erb +219 -0
- data/examples/chef/cookbooks/sidekiq/templates/default/sidekiq.yml.erb +28 -0
- data/examples/monitrc.conf +6 -0
- data/examples/por.rb +10 -0
- data/lib/sidekiq.rb +70 -0
- data/lib/sidekiq/cli.rb +72 -30
- data/lib/sidekiq/client.rb +16 -16
- data/lib/sidekiq/extensions/action_mailer.rb +27 -0
- data/lib/sidekiq/extensions/active_record.rb +29 -0
- data/lib/sidekiq/extensions/generic_proxy.rb +21 -0
- data/lib/sidekiq/manager.rb +16 -12
- data/lib/sidekiq/middleware/chain.rb +23 -23
- data/lib/sidekiq/middleware/client/resque_web_compatibility.rb +1 -4
- data/lib/sidekiq/middleware/client/unique_jobs.rb +5 -13
- data/lib/sidekiq/middleware/server/failure_jobs.rb +24 -0
- data/lib/sidekiq/middleware/server/unique_jobs.rb +1 -5
- data/lib/sidekiq/processor.rb +11 -13
- data/lib/sidekiq/redis_connection.rb +1 -1
- data/lib/sidekiq/util.rb +20 -1
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/worker.rb +1 -1
- data/myapp/Gemfile +0 -2
- data/myapp/app/controllers/work_controller.rb +25 -1
- data/myapp/app/mailers/user_mailer.rb +9 -0
- data/myapp/app/models/post.rb +3 -0
- data/myapp/app/views/user_mailer/greetings.html.erb +3 -0
- data/myapp/app/workers/hard_worker.rb +2 -2
- data/myapp/config/initializers/sidekiq.rb +6 -1
- data/myapp/config/routes.rb +3 -0
- data/sidekiq.gemspec +2 -0
- data/test/config.yml +11 -0
- data/test/test_cli.rb +119 -3
- data/test/test_client.rb +21 -10
- data/test/test_extensions.rb +45 -0
- data/test/test_manager.rb +2 -2
- data/test/test_middleware.rb +7 -12
- data/test/test_stats.rb +1 -2
- metadata +55 -16
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'multi_json'
|
1
2
|
require 'digest'
|
2
3
|
|
3
4
|
module Sidekiq
|
@@ -6,24 +7,15 @@ module Sidekiq
|
|
6
7
|
class UniqueJobs
|
7
8
|
HASH_KEY_EXPIRATION = 30 * 60
|
8
9
|
|
9
|
-
def initialize(redis)
|
10
|
-
@redis = redis
|
11
|
-
end
|
12
|
-
|
13
10
|
def call(item, queue)
|
14
11
|
payload_hash = Digest::MD5.hexdigest(MultiJson.encode(item))
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
Sidekiq.redis.with_connection do |redis|
|
13
|
+
return if redis.get(payload_hash)
|
14
|
+
redis.setex(payload_hash, HASH_KEY_EXPIRATION, 1)
|
15
|
+
end
|
18
16
|
|
19
17
|
yield
|
20
18
|
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def already_scheduled?(payload_hash)
|
25
|
-
!!@redis.get(payload_hash)
|
26
|
-
end
|
27
19
|
end
|
28
20
|
end
|
29
21
|
end
|
@@ -0,0 +1,24 @@
|
|
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
|
+
|
18
|
+
Sidekiq.redis.rpush(:failed, MultiJson.encode(data))
|
19
|
+
raise
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -2,14 +2,10 @@ module Sidekiq
|
|
2
2
|
module Middleware
|
3
3
|
module Server
|
4
4
|
class UniqueJobs
|
5
|
-
def initialize(redis)
|
6
|
-
@redis = redis
|
7
|
-
end
|
8
|
-
|
9
5
|
def call(*args)
|
10
6
|
yield
|
11
7
|
ensure
|
12
|
-
|
8
|
+
Sidekiq.redis.del(Digest::MD5.hexdigest(MultiJson.encode(args[1])))
|
13
9
|
end
|
14
10
|
end
|
15
11
|
end
|
data/lib/sidekiq/processor.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'celluloid'
|
2
|
-
|
3
2
|
require 'sidekiq/util'
|
4
|
-
|
3
|
+
|
5
4
|
require 'sidekiq/middleware/server/active_record'
|
6
5
|
require 'sidekiq/middleware/server/airbrake'
|
7
6
|
require 'sidekiq/middleware/server/unique_jobs'
|
7
|
+
require 'sidekiq/middleware/server/failure_jobs'
|
8
8
|
|
9
9
|
module Sidekiq
|
10
10
|
class Processor
|
@@ -12,16 +12,14 @@ module Sidekiq
|
|
12
12
|
include Celluloid
|
13
13
|
|
14
14
|
def self.middleware
|
15
|
-
|
16
|
-
|
15
|
+
raise "Sidekiq::Processor.middleware is now Sidekiq.server_middleware"
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
chain
|
18
|
+
def self.default_middleware
|
19
|
+
Middleware::Chain.new do |m|
|
20
|
+
m.add Middleware::Server::Airbrake
|
21
|
+
m.add Middleware::Server::UniqueJobs
|
22
|
+
m.add Middleware::Server::ActiveRecord
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
@@ -34,7 +32,7 @@ module Sidekiq
|
|
34
32
|
klass = constantize(msg['class'])
|
35
33
|
worker = klass.new
|
36
34
|
stats(worker, msg, queue) do
|
37
|
-
|
35
|
+
Sidekiq.server_middleware.invoke(worker, msg, queue) do
|
38
36
|
worker.perform(*msg['args'])
|
39
37
|
end
|
40
38
|
end
|
@@ -47,7 +45,7 @@ module Sidekiq
|
|
47
45
|
end
|
48
46
|
|
49
47
|
def to_s
|
50
|
-
@str ||= "#{hostname}:#{
|
48
|
+
@str ||= "#{hostname}:#{process_id}-#{Thread.current.object_id}:default"
|
51
49
|
end
|
52
50
|
|
53
51
|
private
|
@@ -6,7 +6,7 @@ module Sidekiq
|
|
6
6
|
def self.create(options={})
|
7
7
|
url = options[:url] || ENV['REDISTOGO_URL'] || 'redis://localhost:6379/0'
|
8
8
|
client = build_client(url, options[:namespace])
|
9
|
-
return ConnectionPool.new(:timeout => 1, :size => 25) { client } unless options[:use_pool] == false
|
9
|
+
return ConnectionPool.new(:timeout => 1, :size => (options[:size] || Sidekiq.options[:concurrency] || 25)) { client } unless options[:use_pool] == false
|
10
10
|
client
|
11
11
|
end
|
12
12
|
|
data/lib/sidekiq/util.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'logger'
|
2
2
|
|
3
3
|
module Sidekiq
|
4
|
+
##
|
5
|
+
# This module is part of Sidekiq core and not intended for extensions.
|
6
|
+
#
|
4
7
|
module Util
|
5
8
|
|
6
9
|
def self.logger
|
@@ -39,7 +42,23 @@ module Sidekiq
|
|
39
42
|
end
|
40
43
|
|
41
44
|
def redis
|
42
|
-
Sidekiq
|
45
|
+
Sidekiq.redis
|
46
|
+
end
|
47
|
+
|
48
|
+
def process_id
|
49
|
+
Sidekiq::Util.process_id
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.process_id
|
53
|
+
@pid ||= begin
|
54
|
+
if Process.pid == 1
|
55
|
+
# Heroku does not expose pids.
|
56
|
+
require 'securerandom'
|
57
|
+
(SecureRandom.random_number * 4_000_000_000).floor.to_s(16)
|
58
|
+
else
|
59
|
+
Process.pid
|
60
|
+
end
|
61
|
+
end
|
43
62
|
end
|
44
63
|
end
|
45
64
|
end
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/worker.rb
CHANGED
data/myapp/Gemfile
CHANGED
@@ -3,7 +3,31 @@ class WorkController < ApplicationController
|
|
3
3
|
@count = rand(100)
|
4
4
|
puts "Adding #{@count} jobs"
|
5
5
|
@count.times do |x|
|
6
|
-
HardWorker.perform_async('bubba', x)
|
6
|
+
HardWorker.perform_async('bubba', 0.01, x)
|
7
7
|
end
|
8
8
|
end
|
9
|
+
|
10
|
+
def email
|
11
|
+
UserMailer.delay.greetings(Time.now)
|
12
|
+
render :nothing => true
|
13
|
+
end
|
14
|
+
|
15
|
+
def long
|
16
|
+
10.times do |x|
|
17
|
+
HardWorker.perform_async('bob', 10, x)
|
18
|
+
end
|
19
|
+
render :text => 'enqueued'
|
20
|
+
end
|
21
|
+
|
22
|
+
def delayed_post
|
23
|
+
p = Post.first
|
24
|
+
unless p
|
25
|
+
p = Post.create!(:title => "Title!", :body => 'Body!')
|
26
|
+
p2 = Post.create!(:title => "Other!", :body => 'Second Body!')
|
27
|
+
else
|
28
|
+
p2 = Post.second
|
29
|
+
end
|
30
|
+
p.delay.long_method(p2)
|
31
|
+
render :nothing => true
|
32
|
+
end
|
9
33
|
end
|
data/myapp/app/models/post.rb
CHANGED
@@ -1 +1,6 @@
|
|
1
|
-
Sidekiq
|
1
|
+
Sidekiq.configure_client do |config|
|
2
|
+
config.redis = Sidekiq::RedisConnection.create(:namespace => 'resque', :size => 2)
|
3
|
+
end
|
4
|
+
Sidekiq.configure_server do |config|
|
5
|
+
config.redis = Sidekiq::RedisConnection.create(:namespace => 'resque', :size => 25)
|
6
|
+
end
|
data/myapp/config/routes.rb
CHANGED
data/sidekiq.gemspec
CHANGED
data/test/config.yml
ADDED
data/test/test_cli.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'helper'
|
2
2
|
require 'sidekiq/cli'
|
3
|
+
require 'tempfile'
|
3
4
|
|
4
5
|
class TestCli < MiniTest::Unit::TestCase
|
5
6
|
describe 'with cli' do
|
@@ -21,17 +22,132 @@ class TestCli < MiniTest::Unit::TestCase
|
|
21
22
|
|
22
23
|
it 'changes concurrency' do
|
23
24
|
@cli.parse(['sidekiq', '-c', '60', '-r', './test/fake_env.rb'])
|
24
|
-
assert_equal 60,
|
25
|
+
assert_equal 60, Sidekiq.options[:concurrency]
|
25
26
|
end
|
26
27
|
|
27
28
|
it 'changes queues' do
|
28
29
|
@cli.parse(['sidekiq', '-q', 'foo', '-r', './test/fake_env.rb'])
|
29
|
-
assert_equal ['foo'],
|
30
|
+
assert_equal ['foo'], Sidekiq.options[:queues]
|
30
31
|
end
|
31
32
|
|
32
33
|
it 'handles weights' do
|
33
34
|
@cli.parse(['sidekiq', '-q', 'foo,3', '-q', 'bar', '-r', './test/fake_env.rb'])
|
34
|
-
assert_equal %w(bar foo foo foo),
|
35
|
+
assert_equal %w(bar foo foo foo), Sidekiq.options[:queues].sort
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'with pidfile' do
|
39
|
+
before do
|
40
|
+
@tmp_file = Tempfile.new('sidekiq-test')
|
41
|
+
@tmp_path = @tmp_file.path
|
42
|
+
@tmp_file.close!
|
43
|
+
|
44
|
+
@cli.parse(['sidekiq', '-P', @tmp_path, '-r', './test/fake_env.rb'])
|
45
|
+
end
|
46
|
+
|
47
|
+
after do
|
48
|
+
File.unlink @tmp_path if File.exist? @tmp_path
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'sets pidfile path' do
|
52
|
+
assert_equal @tmp_path, Sidekiq.options[:pidfile]
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'writes pidfile' do
|
56
|
+
assert_equal File.read(@tmp_path).strip.to_i, Process.pid
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'with config file' do
|
61
|
+
before do
|
62
|
+
@cli.parse(['sidekiq', '-C', './test/config.yml'])
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'takes a path' do
|
66
|
+
assert_equal './test/config.yml', Sidekiq.options[:config_file]
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'sets verbose' do
|
70
|
+
refute Sidekiq.options[:verbose]
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'sets namespace' do
|
74
|
+
assert_equal "test_namespace", Sidekiq.options[:namespace]
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'sets require file' do
|
78
|
+
assert_equal './test/fake_env.rb', Sidekiq.options[:require]
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'sets environment' do
|
82
|
+
assert_equal 'xzibit', Sidekiq.options[:environment]
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'sets concurrency' do
|
86
|
+
assert_equal 50, Sidekiq.options[:concurrency]
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'sets pid file' do
|
90
|
+
assert_equal '/tmp/sidekiq-config-test.pid', Sidekiq.options[:pidfile]
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'sets queues' do
|
94
|
+
assert_equal 2, Sidekiq.options[:queues].select{ |q| q == 'often' }.length
|
95
|
+
assert_equal 1, Sidekiq.options[:queues].select{ |q| q == 'seldom' }.length
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe 'with config file and flags' do
|
100
|
+
before do
|
101
|
+
# We need an actual file here.
|
102
|
+
@tmp_lib_path = '/tmp/require-me.rb'
|
103
|
+
File.open(@tmp_lib_path, 'w') do |f|
|
104
|
+
f.puts "# do work"
|
105
|
+
end
|
106
|
+
|
107
|
+
@tmp_file = Tempfile.new('sidekiqr')
|
108
|
+
@tmp_path = @tmp_file.path
|
109
|
+
@tmp_file.close!
|
110
|
+
|
111
|
+
@cli.parse(['sidekiq',
|
112
|
+
'-C', './test/config.yml',
|
113
|
+
'-n', 'sweet_story_bro',
|
114
|
+
'-e', 'snoop',
|
115
|
+
'-c', '100',
|
116
|
+
'-r', @tmp_lib_path,
|
117
|
+
'-P', @tmp_path,
|
118
|
+
'-q', 'often,7',
|
119
|
+
'-q', 'seldom,3'])
|
120
|
+
end
|
121
|
+
|
122
|
+
after do
|
123
|
+
File.unlink @tmp_lib_path if File.exist? @tmp_lib_path
|
124
|
+
File.unlink @tmp_path if File.exist? @tmp_path
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'uses concurrency flag' do
|
128
|
+
assert_equal 100, Sidekiq.options[:concurrency]
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'uses namespace flag' do
|
132
|
+
assert_equal "sweet_story_bro", Sidekiq.options[:namespace]
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'uses require file flag' do
|
136
|
+
assert_equal @tmp_lib_path, Sidekiq.options[:require]
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'uses environment flag' do
|
140
|
+
assert_equal 'snoop', Sidekiq.options[:environment]
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'uses pidfile flag' do
|
144
|
+
assert_equal @tmp_path, Sidekiq.options[:pidfile]
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'sets queues' do
|
148
|
+
assert_equal 7, Sidekiq.options[:queues].select{ |q| q == 'often' }.length
|
149
|
+
assert_equal 3, Sidekiq.options[:queues].select{ |q| q == 'seldom' }.length
|
150
|
+
end
|
35
151
|
end
|
36
152
|
|
37
153
|
def new_cli
|