sidekiq 0.10.1 → 0.11.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/Changes.md +13 -0
- data/bin/sidekiq +1 -8
- data/examples/config.yml +2 -2
- data/examples/por.rb +2 -2
- data/examples/sinkiq.rb +4 -2
- data/lib/sidekiq/cli.rb +13 -9
- data/lib/sidekiq/client.rb +12 -16
- data/lib/sidekiq/extensions/generic_proxy.rb +1 -1
- data/lib/sidekiq/fetch.rb +46 -0
- data/lib/sidekiq/manager.rb +47 -61
- data/lib/sidekiq/middleware/client/unique_jobs.rb +16 -12
- data/lib/sidekiq/middleware/server/retry_jobs.rb +2 -0
- data/lib/sidekiq/redis_connection.rb +1 -0
- data/lib/sidekiq/retry.rb +2 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +3 -2
- data/lib/sidekiq/worker.rb +24 -1
- data/myapp/Gemfile +1 -1
- data/sidekiq.gemspec +1 -1
- data/test/config.yml +2 -2
- data/test/test_cli.rb +7 -9
- data/test/test_client.rb +12 -10
- data/test/test_manager.rb +2 -2
- data/test/test_retry.rb +14 -2
- data/test/test_web.rb +1 -1
- metadata +27 -26
data/Changes.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
HEAD
|
2
|
+
-----------
|
3
|
+
|
4
|
+
- Client-side API changes, added sidekiq\_options for Sidekiq::Worker.
|
5
|
+
As a side effect of this change, the client API works on Ruby 1.8.
|
6
|
+
It's not officially supported but should work [#103]
|
7
|
+
- NO POLL! Sidekiq no longer polls Redis, leading to lower network
|
8
|
+
utilization and lower latency for message processing. As a side
|
9
|
+
effect of this change, queue weights are no longer supported. If you
|
10
|
+
wish to process multiple queues, list them in the order you want
|
11
|
+
them processed: `sidekiq -q critical -q high -q default -q low`
|
12
|
+
- Add --version CLI option
|
13
|
+
|
1
14
|
0.10.1
|
2
15
|
-----------
|
3
16
|
|
data/bin/sidekiq
CHANGED
@@ -1,13 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
require 'sidekiq/cli'
|
5
|
-
rescue LoadError
|
6
|
-
# Better way to do this in dev?
|
7
|
-
dir = File.expand_path(File.dirname(__FILE__) + '/../lib')
|
8
|
-
$LOAD_PATH << dir if File.exist?("#{dir}/sidekiq.rb")
|
9
|
-
require 'sidekiq/cli'
|
10
|
-
end
|
3
|
+
require_relative '../lib/sidekiq/cli'
|
11
4
|
|
12
5
|
begin
|
13
6
|
cli = Sidekiq::CLI.instance
|
data/examples/config.yml
CHANGED
data/examples/por.rb
CHANGED
@@ -2,12 +2,12 @@ require 'sidekiq'
|
|
2
2
|
|
3
3
|
# If your client is single-threaded, we just need a single connection in our Redis connection pool
|
4
4
|
Sidekiq.configure_client do |config|
|
5
|
-
config.redis =
|
5
|
+
config.redis = { :namespace => 'x', :size => 1, :url => 'redis://redis.host:1234/14' }
|
6
6
|
end
|
7
7
|
|
8
8
|
# Sidekiq server is multi-threaded so our Redis connection pool size defaults to concurrency (-c)
|
9
9
|
Sidekiq.configure_server do |config|
|
10
|
-
config.redis =
|
10
|
+
config.redis = { :namespace => 'x', :url => 'redis://redis.host:1234/14' }
|
11
11
|
end
|
12
12
|
|
13
13
|
# Start up sidekiq via
|
data/examples/sinkiq.rb
CHANGED
@@ -5,8 +5,10 @@
|
|
5
5
|
# and then browse to http://localhost:4567
|
6
6
|
#
|
7
7
|
require 'sinatra'
|
8
|
-
require 'sidekiq
|
9
|
-
|
8
|
+
require 'sidekiq'
|
9
|
+
require 'redis'
|
10
|
+
|
11
|
+
$redis = Redis.connect
|
10
12
|
|
11
13
|
class SinatraWorker
|
12
14
|
include Sidekiq::Worker
|
data/lib/sidekiq/cli.rb
CHANGED
@@ -18,9 +18,12 @@ end
|
|
18
18
|
require 'yaml'
|
19
19
|
require 'singleton'
|
20
20
|
require 'optparse'
|
21
|
+
require 'celluloid'
|
22
|
+
|
21
23
|
require 'sidekiq'
|
22
24
|
require 'sidekiq/util'
|
23
25
|
require 'sidekiq/manager'
|
26
|
+
require 'sidekiq/retry'
|
24
27
|
|
25
28
|
module Sidekiq
|
26
29
|
class CLI
|
@@ -96,7 +99,6 @@ module Sidekiq
|
|
96
99
|
|
97
100
|
def validate!
|
98
101
|
options[:queues] << 'default' if options[:queues].empty?
|
99
|
-
options[:queues].shuffle!
|
100
102
|
|
101
103
|
if !File.exist?(options[:require]) ||
|
102
104
|
(File.directory?(options[:require]) && !File.exist?("#{options[:require]}/config/application.rb"))
|
@@ -113,9 +115,8 @@ module Sidekiq
|
|
113
115
|
opts = {}
|
114
116
|
|
115
117
|
@parser = OptionParser.new do |o|
|
116
|
-
o.on "-q", "--queue QUEUE
|
117
|
-
(
|
118
|
-
parse_queues(opts, q, weight)
|
118
|
+
o.on "-q", "--queue QUEUE", "Queue to process" do |arg|
|
119
|
+
parse_queues(opts, arg)
|
119
120
|
end
|
120
121
|
|
121
122
|
o.on "-v", "--verbose", "Print more verbose output" do
|
@@ -145,6 +146,11 @@ module Sidekiq
|
|
145
146
|
o.on '-C', '--config PATH', "path to YAML config file" do |arg|
|
146
147
|
opts[:config_file] = arg
|
147
148
|
end
|
149
|
+
|
150
|
+
o.on '-V', '--version', "Print version and exit" do |arg|
|
151
|
+
puts "Sidekiq #{Sidekiq::VERSION}"
|
152
|
+
die(0)
|
153
|
+
end
|
148
154
|
end
|
149
155
|
|
150
156
|
@parser.banner = "sidekiq [options]"
|
@@ -169,15 +175,13 @@ module Sidekiq
|
|
169
175
|
if cli[:config_file] && File.exist?(cli[:config_file])
|
170
176
|
opts = YAML.load_file cli[:config_file]
|
171
177
|
queues = opts.delete(:queues) || []
|
172
|
-
queues.each { |
|
178
|
+
queues.each { |name, _| parse_queues(opts, name) }
|
173
179
|
end
|
174
180
|
opts
|
175
181
|
end
|
176
182
|
|
177
|
-
def parse_queues(opts, q
|
178
|
-
(
|
179
|
-
(opts[:queues] ||= []) << q
|
180
|
-
end
|
183
|
+
def parse_queues(opts, q)
|
184
|
+
(opts[:queues] ||= []) << q
|
181
185
|
end
|
182
186
|
|
183
187
|
end
|
data/lib/sidekiq/client.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'multi_json'
|
2
|
-
require 'redis'
|
3
2
|
|
4
3
|
require 'sidekiq/middleware/chain'
|
5
4
|
require 'sidekiq/middleware/client/unique_jobs'
|
@@ -7,10 +6,6 @@ require 'sidekiq/middleware/client/unique_jobs'
|
|
7
6
|
module Sidekiq
|
8
7
|
class Client
|
9
8
|
|
10
|
-
def self.middleware
|
11
|
-
raise "Sidekiq::Client.middleware is now Sidekiq.client_middleware"
|
12
|
-
end
|
13
|
-
|
14
9
|
def self.default_middleware
|
15
10
|
Middleware::Chain.new do |m|
|
16
11
|
m.add Middleware::Client::UniqueJobs
|
@@ -25,22 +20,25 @@ module Sidekiq
|
|
25
20
|
Sidekiq.redis { |x| x.smembers('queues') }
|
26
21
|
end
|
27
22
|
|
23
|
+
# DEPRECATED
|
28
24
|
def self.queue_mappings
|
29
25
|
@queue_mappings ||= {}
|
30
26
|
end
|
31
27
|
|
32
28
|
# Example usage:
|
33
|
-
# Sidekiq::Client.push('my_queue', 'class' => MyWorker, 'args' => ['foo', 1, :bat => 'bar'])
|
34
|
-
def self.push(
|
35
|
-
raise(ArgumentError, "Message must be a Hash of the form: { 'class' =>
|
29
|
+
# Sidekiq::Client.push('queue' => 'my_queue', 'class' => MyWorker, 'args' => ['foo', 1, :bat => 'bar'])
|
30
|
+
def self.push(item)
|
31
|
+
raise(ArgumentError, "Message must be a Hash of the form: { 'class' => SomeWorker, 'args' => ['bob', 1, :foo => 'bar'] }") unless item.is_a?(Hash)
|
36
32
|
raise(ArgumentError, "Message must include a class and set of arguments: #{item.inspect}") if !item['class'] || !item['args']
|
33
|
+
raise(ArgumentError, "Message must include a Sidekiq::Worker class, not class name: #{item['class'].ancestors.inspect}") if !item['class'].is_a?(Class) || !item['class'].respond_to?('get_sidekiq_options')
|
37
34
|
|
38
|
-
|
39
|
-
|
40
|
-
|
35
|
+
item['retry'] = !!item['class'].get_sidekiq_options['retry']
|
36
|
+
queue = item['queue'] || item['class'].get_sidekiq_options['queue'] || queue_mappings[item['class'].to_s] || 'default'
|
37
|
+
worker_class = item['class']
|
38
|
+
item['class'] = item['class'].to_s
|
41
39
|
|
42
40
|
pushed = false
|
43
|
-
Sidekiq.client_middleware.invoke(item, queue) do
|
41
|
+
Sidekiq.client_middleware.invoke(worker_class, item, queue) do
|
44
42
|
payload = MultiJson.encode(item)
|
45
43
|
Sidekiq.redis do |conn|
|
46
44
|
conn.multi do
|
@@ -53,16 +51,14 @@ module Sidekiq
|
|
53
51
|
pushed
|
54
52
|
end
|
55
53
|
|
56
|
-
#
|
57
|
-
#
|
58
|
-
# Example usage:
|
54
|
+
# Redis compatibility helper. Example usage:
|
59
55
|
#
|
60
56
|
# Sidekiq::Client.enqueue(MyWorker, 'foo', 1, :bat => 'bar')
|
61
57
|
#
|
62
58
|
# Messages are enqueued to the 'default' queue.
|
63
59
|
#
|
64
60
|
def self.enqueue(klass, *args)
|
65
|
-
push(
|
61
|
+
push('class' => klass, 'args' => args)
|
66
62
|
end
|
67
63
|
end
|
68
64
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'sidekiq'
|
2
|
+
require 'celluloid'
|
3
|
+
|
4
|
+
module Sidekiq
|
5
|
+
##
|
6
|
+
# The Fetcher blocks on Redis, waiting for a message to process
|
7
|
+
# from the queues. It gets the message and hands it to the Manager
|
8
|
+
# to assign to a ready Processor.
|
9
|
+
class Fetcher
|
10
|
+
include Celluloid
|
11
|
+
include Sidekiq::Util
|
12
|
+
|
13
|
+
TIMEOUT = 1
|
14
|
+
|
15
|
+
def initialize(mgr, queues)
|
16
|
+
@cmd = queues.map { |q| "queue:#{q}" }
|
17
|
+
@mgr = mgr
|
18
|
+
|
19
|
+
# One second timeout for blpop.
|
20
|
+
@cmd << TIMEOUT
|
21
|
+
end
|
22
|
+
|
23
|
+
# Fetching is straightforward: the Manager makes a fetch
|
24
|
+
# request for each idle processor when Sidekiq starts and
|
25
|
+
# then issues a new fetch request every time a Processor
|
26
|
+
# finishes a message.
|
27
|
+
#
|
28
|
+
# Because we have to shut down cleanly, we can't block
|
29
|
+
# forever and we can't loop forever. Instead we reschedule
|
30
|
+
# a new fetch if the current fetch turned up nothing.
|
31
|
+
def fetch
|
32
|
+
watchdog('Fetcher#fetch died') do
|
33
|
+
queue = nil
|
34
|
+
msg = nil
|
35
|
+
Sidekiq.redis { |conn| (queue, msg) = conn.blpop(*@cmd) }
|
36
|
+
|
37
|
+
if msg
|
38
|
+
@mgr.assign!(msg, queue.gsub(/\Aqueue:/, ''))
|
39
|
+
else
|
40
|
+
after(0) { fetch }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
data/lib/sidekiq/manager.rb
CHANGED
@@ -1,16 +1,15 @@
|
|
1
1
|
require 'celluloid'
|
2
|
-
require 'redis'
|
3
2
|
require 'multi_json'
|
4
3
|
|
5
4
|
require 'sidekiq/util'
|
6
5
|
require 'sidekiq/processor'
|
7
|
-
require '
|
6
|
+
require 'sidekiq/fetch'
|
8
7
|
|
9
8
|
module Sidekiq
|
10
9
|
|
11
10
|
##
|
12
11
|
# The main router in the system. This
|
13
|
-
# manages the processor state and
|
12
|
+
# manages the processor state and accepts messages
|
14
13
|
# from Redis to be dispatched to an idle processor.
|
15
14
|
#
|
16
15
|
class Manager
|
@@ -24,46 +23,50 @@ module Sidekiq
|
|
24
23
|
logger.info "Running in #{RUBY_DESCRIPTION}"
|
25
24
|
logger.debug { options.inspect }
|
26
25
|
@count = options[:concurrency] || 25
|
27
|
-
@queues = options[:queues]
|
28
26
|
@done_callback = nil
|
29
27
|
|
30
28
|
@done = false
|
31
29
|
@busy = []
|
30
|
+
@fetcher = Fetcher.new(current_actor, options[:queues])
|
32
31
|
@ready = @count.times.map { Processor.new_link(current_actor) }
|
33
32
|
end
|
34
33
|
|
35
34
|
def stop(options={})
|
36
|
-
|
37
|
-
|
35
|
+
watchdog('Manager#stop died') do
|
36
|
+
shutdown = options[:shutdown]
|
37
|
+
timeout = options[:timeout]
|
38
38
|
|
39
|
-
|
40
|
-
@ready.each { |x| x.terminate if x.alive? }
|
41
|
-
@ready.clear
|
39
|
+
@done = true
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
conn.srem('workers', name) if name =~ /:#{process_id}-/
|
47
|
-
end
|
48
|
-
end
|
41
|
+
@fetcher.terminate if @fetcher.alive?
|
42
|
+
@ready.each { |x| x.terminate if x.alive? }
|
43
|
+
@ready.clear
|
49
44
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
logger.info { "Pausing #{timeout} seconds to allow workers to finish..." }
|
45
|
+
redis do |conn|
|
46
|
+
workers = conn.smembers('workers')
|
47
|
+
workers.each do |name|
|
48
|
+
conn.srem('workers', name) if name =~ /:#{process_id}-/
|
49
|
+
end
|
56
50
|
end
|
57
51
|
|
58
|
-
|
59
|
-
@busy.
|
60
|
-
|
52
|
+
if shutdown
|
53
|
+
if @busy.empty?
|
54
|
+
# after(0) needed to avoid deadlock in Celluoid after USR1 + TERM
|
55
|
+
return after(0) { signal(:shutdown) }
|
56
|
+
else
|
57
|
+
logger.info { "Pausing #{timeout} seconds to allow workers to finish..." }
|
58
|
+
end
|
59
|
+
|
60
|
+
after(timeout) do
|
61
|
+
@busy.each { |x| x.terminate if x.alive? }
|
62
|
+
signal(:shutdown)
|
63
|
+
end
|
61
64
|
end
|
62
65
|
end
|
63
66
|
end
|
64
67
|
|
65
68
|
def start
|
66
|
-
dispatch
|
69
|
+
@ready.each { dispatch }
|
67
70
|
end
|
68
71
|
|
69
72
|
def when_done(&blk)
|
@@ -71,7 +74,7 @@ module Sidekiq
|
|
71
74
|
end
|
72
75
|
|
73
76
|
def processor_done(processor)
|
74
|
-
watchdog('
|
77
|
+
watchdog('Manager#processor_done died') do
|
75
78
|
@done_callback.call(processor) if @done_callback
|
76
79
|
@busy.delete(processor)
|
77
80
|
if stopped?
|
@@ -85,53 +88,36 @@ module Sidekiq
|
|
85
88
|
end
|
86
89
|
|
87
90
|
def processor_died(processor, reason)
|
88
|
-
|
91
|
+
watchdog("Manager#processor_died died") do
|
92
|
+
@busy.delete(processor)
|
89
93
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
94
|
+
unless stopped?
|
95
|
+
@ready << Processor.new_link(current_actor)
|
96
|
+
dispatch
|
97
|
+
else
|
98
|
+
signal(:shutdown) if @busy.empty?
|
99
|
+
end
|
95
100
|
end
|
96
101
|
end
|
97
102
|
|
98
|
-
|
99
|
-
|
100
|
-
def find_work(queue)
|
101
|
-
msg = redis { |x| x.lpop("queue:#{queue}") }
|
102
|
-
if msg
|
103
|
+
def assign(msg, queue)
|
104
|
+
watchdog("Manager#assign died") do
|
103
105
|
processor = @ready.pop
|
104
106
|
@busy << processor
|
105
107
|
processor.process!(MultiJson.decode(msg), queue)
|
106
108
|
end
|
107
|
-
!!msg
|
108
109
|
end
|
109
110
|
|
110
|
-
|
111
|
-
watchdog("Fatal error in sidekiq, dispatch loop died") do
|
112
|
-
return if stopped?
|
113
|
-
|
114
|
-
# This is a safety check to ensure we haven't leaked
|
115
|
-
# processors somehow.
|
116
|
-
raise "BUG: No processors, cannot continue!" if @ready.empty? && @busy.empty?
|
111
|
+
private
|
117
112
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
end
|
125
|
-
break unless found
|
126
|
-
end
|
113
|
+
def dispatch
|
114
|
+
return if stopped?
|
115
|
+
# This is a safety check to ensure we haven't leaked
|
116
|
+
# processors somehow.
|
117
|
+
raise "BUG: No processors, cannot continue!" if @ready.empty? && @busy.empty?
|
118
|
+
raise "No ready processor!?" if @ready.empty?
|
127
119
|
|
128
|
-
|
129
|
-
# second for work, even if there was nothing to do this time
|
130
|
-
# around.
|
131
|
-
after(1) do
|
132
|
-
dispatch(schedule)
|
133
|
-
end if schedule
|
134
|
-
end
|
120
|
+
@fetcher.fetch!
|
135
121
|
end
|
136
122
|
|
137
123
|
def stopped?
|
@@ -7,23 +7,27 @@ module Sidekiq
|
|
7
7
|
class UniqueJobs
|
8
8
|
HASH_KEY_EXPIRATION = 30 * 60
|
9
9
|
|
10
|
-
def call(item, queue)
|
11
|
-
|
12
|
-
|
10
|
+
def call(worker_class, item, queue)
|
11
|
+
enabled = worker_class.get_sidekiq_options['unique']
|
12
|
+
if enabled
|
13
|
+
payload_hash = Digest::MD5.hexdigest(MultiJson.encode(item))
|
14
|
+
unique = false
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
+
Sidekiq.redis do |conn|
|
17
|
+
conn.watch(payload_hash)
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
if conn.get(payload_hash)
|
20
|
+
conn.unwatch
|
21
|
+
else
|
22
|
+
unique = conn.multi do
|
23
|
+
conn.setex(payload_hash, HASH_KEY_EXPIRATION, 1)
|
24
|
+
end
|
22
25
|
end
|
23
26
|
end
|
27
|
+
yield if unique
|
28
|
+
else
|
29
|
+
yield
|
24
30
|
end
|
25
|
-
|
26
|
-
yield if unique
|
27
31
|
end
|
28
32
|
|
29
33
|
end
|
data/lib/sidekiq/retry.rb
CHANGED
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'sinatra/base'
|
2
2
|
require 'slim'
|
3
3
|
require 'sprockets'
|
4
|
+
require 'multi_json'
|
4
5
|
|
5
6
|
module Sidekiq
|
6
7
|
class SprocketsMiddleware
|
@@ -41,7 +42,7 @@ module Sidekiq
|
|
41
42
|
Sidekiq.redis do |conn|
|
42
43
|
workers = conn.smembers('workers')
|
43
44
|
workers.each do |name|
|
44
|
-
conn.srem('workers', name)
|
45
|
+
conn.srem('workers', name)
|
45
46
|
end
|
46
47
|
end
|
47
48
|
end
|
@@ -107,7 +108,7 @@ module Sidekiq
|
|
107
108
|
end
|
108
109
|
|
109
110
|
def relative_time(time)
|
110
|
-
|
111
|
+
%{<time datetime="#{time.getutc.iso8601}">#{time}</time>}
|
111
112
|
end
|
112
113
|
end
|
113
114
|
|
data/lib/sidekiq/worker.rb
CHANGED
@@ -26,12 +26,35 @@ module Sidekiq
|
|
26
26
|
|
27
27
|
module ClassMethods
|
28
28
|
def perform_async(*args)
|
29
|
-
Sidekiq::Client.push('class' => self
|
29
|
+
Sidekiq::Client.push('class' => self, 'args' => args)
|
30
30
|
end
|
31
31
|
|
32
32
|
def queue(name)
|
33
|
+
puts "DEPRECATED: `queue :name` is now `sidekiq_options :queue => :name`"
|
33
34
|
Sidekiq::Client.queue_mappings[self.name] = name.to_s
|
34
35
|
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Allows customization for this type of Worker.
|
39
|
+
# Legal options:
|
40
|
+
#
|
41
|
+
# :unique - enable the UniqueJobs middleware for this Worker, default *true*
|
42
|
+
# :queue - use a named queue for this Worker, default 'default'
|
43
|
+
# :retry - enable the RetryJobs middleware for this Worker, default *true*
|
44
|
+
def sidekiq_options(opts={})
|
45
|
+
@sidekiq_options = get_sidekiq_options.merge(stringify_keys(opts || {}))
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_sidekiq_options # :nodoc:
|
49
|
+
@sidekiq_options || { 'unique' => true, 'retry' => true, 'queue' => 'default' }
|
50
|
+
end
|
51
|
+
|
52
|
+
def stringify_keys(hash) # :nodoc:
|
53
|
+
hash.keys.each do |key|
|
54
|
+
hash[key.to_s] = hash.delete(key)
|
55
|
+
end
|
56
|
+
hash
|
57
|
+
end
|
35
58
|
end
|
36
59
|
end
|
37
60
|
end
|
data/myapp/Gemfile
CHANGED
data/sidekiq.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.add_dependency 'redis'
|
17
17
|
gem.add_dependency 'redis-namespace'
|
18
18
|
gem.add_dependency 'connection_pool', '~> 0.9.0'
|
19
|
-
gem.add_dependency 'celluloid'
|
19
|
+
gem.add_dependency 'celluloid', '~> 0.10.0'
|
20
20
|
gem.add_dependency 'multi_json'
|
21
21
|
gem.add_development_dependency 'minitest'
|
22
22
|
gem.add_development_dependency 'sinatra'
|
data/test/config.yml
CHANGED
data/test/test_cli.rb
CHANGED
@@ -45,9 +45,9 @@ class TestCli < MiniTest::Unit::TestCase
|
|
45
45
|
assert_equal 30, Sidekiq.options[:timeout]
|
46
46
|
end
|
47
47
|
|
48
|
-
it 'handles
|
49
|
-
@cli.parse(['sidekiq', '-q', 'foo
|
50
|
-
assert_equal %w(
|
48
|
+
it 'handles multiple queues' do
|
49
|
+
@cli.parse(['sidekiq', '-q', 'foo', '-q', 'bar', '-r', './test/fake_env.rb'])
|
50
|
+
assert_equal %w(foo bar), Sidekiq.options[:queues]
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'sets verbose' do
|
@@ -110,8 +110,7 @@ class TestCli < MiniTest::Unit::TestCase
|
|
110
110
|
end
|
111
111
|
|
112
112
|
it 'sets queues' do
|
113
|
-
assert_equal
|
114
|
-
assert_equal 1, Sidekiq.options[:queues].select{ |q| q == 'seldom' }.length
|
113
|
+
assert_equal %w(often seldom), Sidekiq.options[:queues]
|
115
114
|
end
|
116
115
|
end
|
117
116
|
|
@@ -133,8 +132,8 @@ class TestCli < MiniTest::Unit::TestCase
|
|
133
132
|
'-c', '100',
|
134
133
|
'-r', @tmp_lib_path,
|
135
134
|
'-P', @tmp_path,
|
136
|
-
'-q', 'often
|
137
|
-
'-q', 'seldom
|
135
|
+
'-q', 'often',
|
136
|
+
'-q', 'seldom'])
|
138
137
|
end
|
139
138
|
|
140
139
|
after do
|
@@ -159,8 +158,7 @@ class TestCli < MiniTest::Unit::TestCase
|
|
159
158
|
end
|
160
159
|
|
161
160
|
it 'sets queues' do
|
162
|
-
assert_equal
|
163
|
-
assert_equal 3, Sidekiq.options[:queues].select{ |q| q == 'seldom' }.length
|
161
|
+
assert_equal %w(often seldom), Sidekiq.options[:queues]
|
164
162
|
end
|
165
163
|
end
|
166
164
|
end
|
data/test/test_client.rb
CHANGED
@@ -9,19 +9,21 @@ class TestClient < MiniTest::Unit::TestCase
|
|
9
9
|
Sidekiq.redis {|c| c.flushdb }
|
10
10
|
end
|
11
11
|
|
12
|
+
class QueueWorker
|
13
|
+
include Sidekiq::Worker
|
14
|
+
sidekiq_options :queue => 'customqueue'
|
15
|
+
end
|
16
|
+
|
12
17
|
it 'does not push duplicate messages when configured for unique only' do
|
13
|
-
|
14
|
-
Sidekiq.
|
15
|
-
chain.add Sidekiq::Middleware::Client::UniqueJobs
|
16
|
-
end
|
17
|
-
10.times { Sidekiq::Client.push('customqueue', 'class' => 'Foo', 'args' => [1, 2]) }
|
18
|
+
QueueWorker.sidekiq_options :unique => true
|
19
|
+
10.times { Sidekiq::Client.push('class' => QueueWorker, 'args' => [1, 2]) }
|
18
20
|
assert_equal 1, Sidekiq.redis {|c| c.llen("queue:customqueue") }
|
19
21
|
end
|
20
22
|
|
21
23
|
it 'does push duplicate messages when not configured for unique only' do
|
22
|
-
|
23
|
-
10.times { Sidekiq::Client.push('
|
24
|
-
assert_equal 10, Sidekiq.redis {|c| c.llen("queue:
|
24
|
+
QueueWorker.sidekiq_options :unique => false
|
25
|
+
10.times { Sidekiq::Client.push('class' => QueueWorker, 'args' => [1, 2]) }
|
26
|
+
assert_equal 10, Sidekiq.redis {|c| c.llen("queue:customqueue") }
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
@@ -56,7 +58,7 @@ class TestClient < MiniTest::Unit::TestCase
|
|
56
58
|
|
57
59
|
it 'pushes messages to redis' do
|
58
60
|
@redis.expect :rpush, 1, ['queue:foo', String]
|
59
|
-
pushed = Sidekiq::Client.push('foo', 'class' =>
|
61
|
+
pushed = Sidekiq::Client.push('queue' => 'foo', 'class' => MyWorker, 'args' => [1, 2])
|
60
62
|
assert pushed
|
61
63
|
@redis.verify
|
62
64
|
end
|
@@ -82,7 +84,7 @@ class TestClient < MiniTest::Unit::TestCase
|
|
82
84
|
class QueuedWorker
|
83
85
|
include Sidekiq::Worker
|
84
86
|
|
85
|
-
queue :flimflam
|
87
|
+
sidekiq_options :queue => :flimflam
|
86
88
|
end
|
87
89
|
|
88
90
|
it 'enqueues to the named queue' do
|
data/test/test_manager.rb
CHANGED
@@ -26,8 +26,8 @@ class TestManager < MiniTest::Unit::TestCase
|
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'processes messages' do
|
29
|
-
Sidekiq::Client.push(:foo, 'class' => IntegrationWorker, 'args' => [1, 2])
|
30
|
-
Sidekiq::Client.push(:foo, 'class' => IntegrationWorker, 'args' => [1, 3])
|
29
|
+
Sidekiq::Client.push('queue' => :foo, 'class' => IntegrationWorker, 'args' => [1, 2])
|
30
|
+
Sidekiq::Client.push('queue' => :foo, 'class' => IntegrationWorker, 'args' => [1, 3])
|
31
31
|
|
32
32
|
q = TimedQueue.new
|
33
33
|
mgr = Sidekiq::Manager.new(:queues => [:foo], :concurrency => 2)
|
data/test/test_retry.rb
CHANGED
@@ -12,9 +12,21 @@ class TestRetry < MiniTest::Unit::TestCase
|
|
12
12
|
def @redis.with; yield self; end
|
13
13
|
end
|
14
14
|
|
15
|
+
it 'allows disabling retry' do
|
16
|
+
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => false }
|
17
|
+
msg2 = msg.dup
|
18
|
+
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
19
|
+
assert_raises RuntimeError do
|
20
|
+
handler.call('', msg2, 'default') do
|
21
|
+
raise "kerblammo!"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
assert_equal msg, msg2
|
25
|
+
end
|
26
|
+
|
15
27
|
it 'handles a new failed message' do
|
16
28
|
@redis.expect :zadd, 1, ['retry', String, String]
|
17
|
-
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'] }
|
29
|
+
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
|
18
30
|
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
19
31
|
assert_raises RuntimeError do
|
20
32
|
handler.call('', msg, 'default') do
|
@@ -32,7 +44,7 @@ class TestRetry < MiniTest::Unit::TestCase
|
|
32
44
|
it 'handles a recurring failed message' do
|
33
45
|
@redis.expect :zadd, 1, ['retry', String, String]
|
34
46
|
now = Time.now.utc
|
35
|
-
msg = {"class"=>"Bob", "args"=>[1, 2, "foo"], "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>10}
|
47
|
+
msg = {"class"=>"Bob", "args"=>[1, 2, "foo"], 'retry' => true, "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>10}
|
36
48
|
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
37
49
|
assert_raises RuntimeError do
|
38
50
|
handler.call('', msg, 'default') do
|
data/test/test_web.rb
CHANGED
@@ -38,7 +38,7 @@ class TestWeb < MiniTest::Unit::TestCase
|
|
38
38
|
assert_match last_response.body, /default/
|
39
39
|
refute_match last_response.body, /foo/
|
40
40
|
|
41
|
-
assert Sidekiq::Client.push(:foo, 'class' => WebWorker, 'args' => [1, 3])
|
41
|
+
assert Sidekiq::Client.push('queue' => :foo, 'class' => WebWorker, 'args' => [1, 3])
|
42
42
|
|
43
43
|
get '/'
|
44
44
|
assert_equal 200, last_response.status
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.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-03
|
12
|
+
date: 2012-04-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
16
|
-
requirement: &
|
16
|
+
requirement: &70099857099140 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70099857099140
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: redis-namespace
|
27
|
-
requirement: &
|
27
|
+
requirement: &70099857098700 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70099857098700
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: connection_pool
|
38
|
-
requirement: &
|
38
|
+
requirement: &70099857098200 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,21 +43,21 @@ dependencies:
|
|
43
43
|
version: 0.9.0
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70099857098200
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: celluloid
|
49
|
-
requirement: &
|
49
|
+
requirement: &70099857097700 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 0.10.0
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70099857097700
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: multi_json
|
60
|
-
requirement: &
|
60
|
+
requirement: &70099857097320 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70099857097320
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: minitest
|
71
|
-
requirement: &
|
71
|
+
requirement: &70099857113240 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70099857113240
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: sinatra
|
82
|
-
requirement: &
|
82
|
+
requirement: &70099857112820 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70099857112820
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: slim
|
93
|
-
requirement: &
|
93
|
+
requirement: &70099857112400 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70099857112400
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: rake
|
104
|
-
requirement: &
|
104
|
+
requirement: &70099857111980 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70099857111980
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: actionmailer
|
115
|
-
requirement: &
|
115
|
+
requirement: &70099857111480 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ~>
|
@@ -120,10 +120,10 @@ dependencies:
|
|
120
120
|
version: '3'
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *70099857111480
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: activerecord
|
126
|
-
requirement: &
|
126
|
+
requirement: &70099857110980 !ruby/object:Gem::Requirement
|
127
127
|
none: false
|
128
128
|
requirements:
|
129
129
|
- - ~>
|
@@ -131,7 +131,7 @@ dependencies:
|
|
131
131
|
version: '3'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
|
-
version_requirements: *
|
134
|
+
version_requirements: *70099857110980
|
135
135
|
description: Simple, efficient message processing for Ruby
|
136
136
|
email:
|
137
137
|
- mperham@gmail.com
|
@@ -172,6 +172,7 @@ files:
|
|
172
172
|
- lib/sidekiq/extensions/action_mailer.rb
|
173
173
|
- lib/sidekiq/extensions/active_record.rb
|
174
174
|
- lib/sidekiq/extensions/generic_proxy.rb
|
175
|
+
- lib/sidekiq/fetch.rb
|
175
176
|
- lib/sidekiq/manager.rb
|
176
177
|
- lib/sidekiq/middleware/chain.rb
|
177
178
|
- lib/sidekiq/middleware/client/unique_jobs.rb
|