sidekiq 2.16.1 → 2.17.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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -3
- data/Changes.md +10 -0
- data/Pro-Changes.md +46 -3
- data/lib/sidekiq/api.rb +1 -1
- data/lib/sidekiq/cli.rb +3 -2
- data/lib/sidekiq/client.rb +5 -3
- data/lib/sidekiq/fetch.rb +5 -3
- data/lib/sidekiq/manager.rb +41 -14
- data/lib/sidekiq/middleware/chain.rb +5 -2
- data/lib/sidekiq/processor.rb +5 -2
- data/lib/sidekiq/redis_connection.rb +11 -5
- data/lib/sidekiq/tasks/sidekiq.rake +13 -7
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +2 -2
- data/lib/sidekiq/web_helpers.rb +9 -1
- data/test/config.yml +0 -1
- data/test/test_client.rb +12 -5
- data/test/test_fetch.rb +1 -1
- data/test/test_manager.rb +2 -0
- data/test/test_middleware.rb +1 -1
- data/test/test_processor.rb +6 -6
- data/test/test_redis_connection.rb +14 -0
- data/test/test_scheduling.rb +1 -1
- data/web/assets/stylesheets/application.css +11 -0
- data/web/views/retries.erb +16 -13
- data/web/views/scheduled.erb +11 -10
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3c94aa8a163d8572aaa7c04bc1fbdf0b2bb737c
|
4
|
+
data.tar.gz: d7cd0118de313f863b5c6ead2163a47e0cb8cdc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce15a352e04acb9be28519faf11a2bbac4cc3deec7467abef232a53679cde91d4a60a5f08bf0143cd3ebde20559e8ee112e2ef270332e27fc8a95814eb7df9cd
|
7
|
+
data.tar.gz: 2ea6a283ea6850816178520608dd37fec6e46ebe72ce933daa02204862f1815d588a02b790b33009c39fe56ff55f90b108f9c445e36875ed8d5f4596c53c4c3a
|
data/.travis.yml
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
language: ruby
|
2
|
+
services:
|
3
|
+
- redis-server
|
2
4
|
rvm:
|
3
5
|
- 1.9.3
|
4
6
|
- jruby-19mode
|
5
|
-
- rbx-
|
7
|
+
- rbx-2.1.1
|
6
8
|
- 2.0.0
|
7
9
|
branches:
|
8
10
|
only:
|
@@ -15,5 +17,4 @@ notifications:
|
|
15
17
|
matrix:
|
16
18
|
allow_failures:
|
17
19
|
- rvm: jruby-19mode
|
18
|
-
- rvm: rbx-
|
19
|
-
- rvm: 2.0.0
|
20
|
+
- rvm: rbx-2.1.1
|
data/Changes.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
2.17.0
|
2
|
+
-----------
|
3
|
+
|
4
|
+
- Change USR1 signal handling to exit process as soon as all workers are quiet. [#1358]
|
5
|
+
- Change `Sidekiq::Client#push_bulk` to return an array of pushed `jid`s. [#1315, barelyknown]
|
6
|
+
- Web UI refactoring to use more API internally (yummy dogfood!)
|
7
|
+
- Much faster Sidekiq::Job#delete performance for larger queue sizes
|
8
|
+
- Further capistrano 3 fixes
|
9
|
+
- Many misc minor fixes
|
10
|
+
|
1
11
|
2.16.1
|
2
12
|
-----------
|
3
13
|
|
data/Pro-Changes.md
CHANGED
@@ -1,13 +1,56 @@
|
|
1
1
|
Sidekiq Pro Changelog
|
2
2
|
=======================
|
3
3
|
|
4
|
-
Please see http://sidekiq.org/pro for more details and how to buy.
|
4
|
+
Please see [http://sidekiq.org/pro](http://sidekiq.org/pro) for more details and how to buy.
|
5
|
+
|
6
|
+
HEAD
|
7
|
+
-----------
|
8
|
+
|
9
|
+
Thanks to @jonhyman for his contributions to this Sidekiq Pro release.
|
10
|
+
|
11
|
+
This release includes new functionality based on the SCAN command newly
|
12
|
+
added to Redis 2.8. Pro still works with Redis 2.4 but some
|
13
|
+
functionality will be unavailable.
|
14
|
+
|
15
|
+
- Job Filtering in the Web UI!
|
16
|
+
You can now filter retries and scheduled jobs in the Web UI so you
|
17
|
+
only see the jobs relevant to your needs. Queues cannot be filtered;
|
18
|
+
Redis does not provide the same SCAN operation on the LIST type.
|
19
|
+
**Redis 2.8 only**
|
20
|
+
- SCAN support in the Sidekiq::SortedSet API. Here's an example that
|
21
|
+
finds all jobs which contain the substring "Warehouse::OrderShip"
|
22
|
+
and deletes all matching retries. If the set is large, this API
|
23
|
+
will be **MUCH** faster than standard iteration using each.
|
24
|
+
**Redis 2.8 only**
|
25
|
+
```ruby
|
26
|
+
Sidekiq::RetrySet.new.scan("Warehouse::OrderShip") do |job|
|
27
|
+
job.delete
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
- Sidekiq::Batch#jobs now returns the set of JIDs added to the batch.
|
32
|
+
- Sidekiq::Batch#jids returns the complete set of JIDs associated with the batch.
|
33
|
+
- Sidekiq::Batch#remove\_jobs(jid, jid, ...) removes JIDs from the set, allowing early termination of jobs if they become irrelevant according to application logic.
|
34
|
+
- Sidekiq::Batch#include?(jid) allows jobs to check if they are still
|
35
|
+
relevant to a Batch and exit early if not.
|
36
|
+
- Sidekiq::SortedSet#find\_job(jid) now uses server-side Lua **Redis 2.6 only** [jonhyman]
|
37
|
+
- The statsd integration now sets global job counts:
|
38
|
+
```ruby
|
39
|
+
jobs.count
|
40
|
+
jobs.success
|
41
|
+
jobs.failure
|
42
|
+
```
|
43
|
+
|
44
|
+
- Change shutdown logic to push leftover jobs in the private queue back
|
45
|
+
into the public queue when shutting down with Reliable Fetch. This
|
46
|
+
allows the safe decommission of a Sidekiq Pro process when autoscaling. [jonhyman]
|
47
|
+
- Pro now requires Sidekiq 2.17.0
|
5
48
|
|
6
49
|
1.2.5
|
7
50
|
-----------
|
8
51
|
|
9
|
-
- Convert Batch UI to use Sidekiq 2.16's support for extension
|
10
|
-
|
52
|
+
- Convert Batch UI to use Sidekiq 2.16's support for extension localization.
|
53
|
+
- Update reliable\_push to work with Sidekiq::Client refactoring in 2.16
|
11
54
|
- Pro now requires Sidekiq 2.16.0
|
12
55
|
|
13
56
|
1.2.4
|
data/lib/sidekiq/api.rb
CHANGED
data/lib/sidekiq/cli.rb
CHANGED
@@ -326,8 +326,9 @@ module Sidekiq
|
|
326
326
|
end
|
327
327
|
ns = opts.delete(:namespace)
|
328
328
|
if ns
|
329
|
-
|
330
|
-
|
329
|
+
# logger hasn't been initialized yet, puts is all we have.
|
330
|
+
puts("namespace should be set in your ruby initializer, is ignored in config file")
|
331
|
+
puts("config.redis = { :url => ..., :namespace => '#{ns}' }")
|
331
332
|
end
|
332
333
|
opts
|
333
334
|
end
|
data/lib/sidekiq/client.rb
CHANGED
@@ -53,7 +53,8 @@ module Sidekiq
|
|
53
53
|
|
54
54
|
##
|
55
55
|
# Push a large number of jobs to Redis. In practice this method is only
|
56
|
-
# useful if you are pushing tens of thousands of jobs or more
|
56
|
+
# useful if you are pushing tens of thousands of jobs or more, or if you need
|
57
|
+
# to ensure that a batch doesn't complete prematurely. This method
|
57
58
|
# basically cuts down on the redis round trip latency.
|
58
59
|
#
|
59
60
|
# Takes the same arguments as #push except that args is expected to be
|
@@ -61,7 +62,7 @@ module Sidekiq
|
|
61
62
|
# is run through the client middleware pipeline and each job gets its own Job ID
|
62
63
|
# as normal.
|
63
64
|
#
|
64
|
-
# Returns
|
65
|
+
# Returns an array of the of pushed jobs' jids or nil if the pushed failed. The number of jobs
|
65
66
|
# pushed can be less than the number given if the middleware stopped processing for one
|
66
67
|
# or more jobs.
|
67
68
|
def push_bulk(items)
|
@@ -73,7 +74,7 @@ module Sidekiq
|
|
73
74
|
|
74
75
|
pushed = false
|
75
76
|
pushed = raw_push(payloads) if !payloads.empty?
|
76
|
-
pushed ? payloads.
|
77
|
+
pushed ? payloads.collect { |payload| payload['jid'] } : nil
|
77
78
|
end
|
78
79
|
|
79
80
|
class << self
|
@@ -186,6 +187,7 @@ module Sidekiq
|
|
186
187
|
normalized_item = Sidekiq.default_worker_options.merge(item)
|
187
188
|
end
|
188
189
|
|
190
|
+
normalized_item['queue'] = normalized_item['queue'].to_s
|
189
191
|
normalized_item['jid'] ||= SecureRandom.hex(12)
|
190
192
|
normalized_item['enqueued_at'] ||= Time.now.to_f
|
191
193
|
normalized_item
|
data/lib/sidekiq/fetch.rb
CHANGED
@@ -41,13 +41,13 @@ module Sidekiq
|
|
41
41
|
after(0) { fetch }
|
42
42
|
end
|
43
43
|
rescue => ex
|
44
|
-
|
44
|
+
handle_fetch_exception(ex)
|
45
45
|
end
|
46
46
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
def
|
50
|
+
def handle_fetch_exception(ex)
|
51
51
|
if !@down
|
52
52
|
logger.error("Error fetching message: #{ex}")
|
53
53
|
ex.backtrace.each do |bt|
|
@@ -90,7 +90,9 @@ module Sidekiq
|
|
90
90
|
UnitOfWork.new(*work) if work
|
91
91
|
end
|
92
92
|
|
93
|
-
|
93
|
+
# By leaving this as a class method, it can be pluggable and used by the Manager actor. Making it
|
94
|
+
# an instance method will make it async to the Fetcher actor
|
95
|
+
def self.bulk_requeue(inprogress, options)
|
94
96
|
Sidekiq.logger.debug { "Re-queueing terminated jobs" }
|
95
97
|
jobs_to_requeue = {}
|
96
98
|
inprogress.each do |unit_of_work|
|
data/lib/sidekiq/manager.rb
CHANGED
@@ -19,8 +19,11 @@ module Sidekiq
|
|
19
19
|
attr_reader :busy
|
20
20
|
attr_accessor :fetcher
|
21
21
|
|
22
|
+
SPIN_TIME_FOR_GRACEFUL_SHUTDOWN = 1
|
23
|
+
|
22
24
|
def initialize(options={})
|
23
25
|
logger.debug { options.inspect }
|
26
|
+
@options = options
|
24
27
|
@count = options[:concurrency] || 25
|
25
28
|
@done_callback = nil
|
26
29
|
|
@@ -37,7 +40,7 @@ module Sidekiq
|
|
37
40
|
|
38
41
|
def stop(options={})
|
39
42
|
watchdog('Manager#stop died') do
|
40
|
-
|
43
|
+
should_shutdown = options[:shutdown]
|
41
44
|
timeout = options[:timeout]
|
42
45
|
|
43
46
|
@done = true
|
@@ -47,10 +50,20 @@ module Sidekiq
|
|
47
50
|
@ready.clear
|
48
51
|
|
49
52
|
clear_worker_set
|
53
|
+
return if clean_up_for_graceful_shutdown
|
54
|
+
|
55
|
+
hard_shutdown_in timeout if should_shutdown
|
56
|
+
end
|
57
|
+
end
|
50
58
|
|
51
|
-
|
52
|
-
|
59
|
+
def clean_up_for_graceful_shutdown
|
60
|
+
if @busy.empty?
|
61
|
+
shutdown
|
62
|
+
return true
|
53
63
|
end
|
64
|
+
|
65
|
+
after(SPIN_TIME_FOR_GRACEFUL_SHUTDOWN) { clean_up_for_graceful_shutdown }
|
66
|
+
false
|
54
67
|
end
|
55
68
|
|
56
69
|
def start
|
@@ -69,7 +82,7 @@ module Sidekiq
|
|
69
82
|
@busy.delete(processor)
|
70
83
|
if stopped?
|
71
84
|
processor.terminate if processor.alive?
|
72
|
-
|
85
|
+
shutdown if @busy.empty?
|
73
86
|
else
|
74
87
|
@ready << processor if processor.alive?
|
75
88
|
end
|
@@ -89,7 +102,7 @@ module Sidekiq
|
|
89
102
|
@ready << p
|
90
103
|
dispatch
|
91
104
|
else
|
92
|
-
|
105
|
+
shutdown if @busy.empty?
|
93
106
|
end
|
94
107
|
end
|
95
108
|
end
|
@@ -151,22 +164,16 @@ module Sidekiq
|
|
151
164
|
# They must die but their messages shall live on.
|
152
165
|
logger.info("Still waiting for #{@busy.size} busy workers")
|
153
166
|
|
154
|
-
|
155
|
-
# NOTE: You may notice that we may push a job back to redis before
|
156
|
-
# the worker thread is terminated. This is ok because Sidekiq's
|
157
|
-
# contract says that jobs are run AT LEAST once. Process termination
|
158
|
-
# is delayed until we're certain the jobs are back in Redis because
|
159
|
-
# it is worse to lose a job than to run it twice.
|
160
|
-
Sidekiq::Fetcher.strategy.bulk_requeue(@in_progress.values)
|
167
|
+
requeue
|
161
168
|
|
162
|
-
logger.
|
169
|
+
logger.warn { "Terminating #{@busy.size} busy worker threads" }
|
163
170
|
@busy.each do |processor|
|
164
171
|
if processor.alive? && t = @threads.delete(processor.object_id)
|
165
172
|
t.raise Shutdown
|
166
173
|
end
|
167
174
|
end
|
168
175
|
|
169
|
-
|
176
|
+
signal_shutdown
|
170
177
|
end
|
171
178
|
end
|
172
179
|
end
|
@@ -184,5 +191,25 @@ module Sidekiq
|
|
184
191
|
def stopped?
|
185
192
|
@done
|
186
193
|
end
|
194
|
+
|
195
|
+
def shutdown
|
196
|
+
requeue
|
197
|
+
signal_shutdown
|
198
|
+
end
|
199
|
+
|
200
|
+
def signal_shutdown
|
201
|
+
after(0) { signal(:shutdown) }
|
202
|
+
end
|
203
|
+
|
204
|
+
def requeue
|
205
|
+
# Re-enqueue terminated jobs
|
206
|
+
# NOTE: You may notice that we may push a job back to redis before
|
207
|
+
# the worker thread is terminated. This is ok because Sidekiq's
|
208
|
+
# contract says that jobs are run AT LEAST once. Process termination
|
209
|
+
# is delayed until we're certain the jobs are back in Redis because
|
210
|
+
# it is worse to lose a job than to run it twice.
|
211
|
+
Sidekiq::Fetcher.strategy.bulk_requeue(@in_progress.values, @options)
|
212
|
+
@in_progress.clear
|
213
|
+
end
|
187
214
|
end
|
188
215
|
end
|
@@ -49,13 +49,16 @@ module Sidekiq
|
|
49
49
|
# end
|
50
50
|
# end
|
51
51
|
#
|
52
|
-
# This is an example of a minimal client middleware
|
52
|
+
# This is an example of a minimal client middleware, note
|
53
|
+
# the method must return the result or the job will not push
|
54
|
+
# to Redis:
|
53
55
|
#
|
54
56
|
# class MyClientHook
|
55
57
|
# def call(worker_class, msg, queue)
|
56
58
|
# puts "Before push"
|
57
|
-
# yield
|
59
|
+
# result = yield
|
58
60
|
# puts "After push"
|
61
|
+
# result
|
59
62
|
# end
|
60
63
|
# end
|
61
64
|
#
|
data/lib/sidekiq/processor.rb
CHANGED
@@ -37,6 +37,7 @@ module Sidekiq
|
|
37
37
|
do_defer do
|
38
38
|
@boss.async.real_thread(proxy_id, Thread.current)
|
39
39
|
|
40
|
+
ack = true
|
40
41
|
begin
|
41
42
|
msg = Sidekiq.load_json(msgstr)
|
42
43
|
klass = msg['class'].constantize
|
@@ -50,12 +51,14 @@ module Sidekiq
|
|
50
51
|
end
|
51
52
|
rescue Sidekiq::Shutdown
|
52
53
|
# Had to force kill this job because it didn't finish
|
53
|
-
# within the timeout.
|
54
|
+
# within the timeout. Don't acknowledge the work since
|
55
|
+
# we didn't properly finish it.
|
56
|
+
ack = false
|
54
57
|
rescue Exception => ex
|
55
58
|
handle_exception(ex, msg || { :message => msgstr })
|
56
59
|
raise
|
57
60
|
ensure
|
58
|
-
work.acknowledge
|
61
|
+
work.acknowledge if ack
|
59
62
|
end
|
60
63
|
end
|
61
64
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'connection_pool'
|
2
2
|
require 'redis'
|
3
|
+
require 'uri'
|
3
4
|
|
4
5
|
module Sidekiq
|
5
6
|
class RedisConnection
|
@@ -10,7 +11,7 @@ module Sidekiq
|
|
10
11
|
if url
|
11
12
|
options[:url] = url
|
12
13
|
end
|
13
|
-
|
14
|
+
|
14
15
|
# need a connection for Fetcher and Retry
|
15
16
|
size = options[:size] || (Sidekiq.server? ? (Sidekiq.options[:concurrency] + 2) : 5)
|
16
17
|
pool_timeout = options[:pool_timeout] || 1
|
@@ -53,18 +54,23 @@ module Sidekiq
|
|
53
54
|
end
|
54
55
|
|
55
56
|
def log_info(options)
|
57
|
+
# Don't log Redis AUTH password
|
58
|
+
scrubbed_options = options.dup
|
59
|
+
if scrubbed_options[:url] && (uri = URI.parse(scrubbed_options[:url])) && uri.password
|
60
|
+
uri.password = "REDACTED"
|
61
|
+
scrubbed_options[:url] = uri.to_s
|
62
|
+
end
|
56
63
|
if Sidekiq.server?
|
57
|
-
Sidekiq.logger.info("Booting Sidekiq #{Sidekiq::VERSION} with redis options #{
|
64
|
+
Sidekiq.logger.info("Booting Sidekiq #{Sidekiq::VERSION} with redis options #{scrubbed_options}")
|
58
65
|
else
|
59
|
-
Sidekiq.logger.info("#{Sidekiq::NAME} client with redis options #{
|
66
|
+
Sidekiq.logger.info("#{Sidekiq::NAME} client with redis options #{scrubbed_options}")
|
60
67
|
end
|
61
68
|
end
|
62
69
|
|
63
70
|
def determine_redis_provider
|
64
71
|
# REDISTOGO_URL is only support for legacy reasons
|
65
|
-
return ENV['REDISTOGO_URL'] if ENV['REDISTOGO_URL']
|
66
72
|
provider = ENV['REDIS_PROVIDER'] || 'REDIS_URL'
|
67
|
-
ENV[provider]
|
73
|
+
ENV[provider] || ENV['REDISTOGO_URL']
|
68
74
|
end
|
69
75
|
|
70
76
|
end
|
@@ -23,6 +23,12 @@ namespace :load do
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
namespace :deploy do
|
27
|
+
before :starting, :check_sidekiq_hooks do
|
28
|
+
invoke 'sidekiq:add_default_hooks' if fetch(:sidekiq_default_hooks)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
26
32
|
namespace :sidekiq do
|
27
33
|
def for_each_process(&block)
|
28
34
|
fetch(:sidekiq_processes).times do |idx|
|
@@ -30,6 +36,13 @@ namespace :sidekiq do
|
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
39
|
+
task :add_default_hooks do
|
40
|
+
after 'deploy:starting', 'sidekiq:quiet'
|
41
|
+
after 'deploy:updated', 'sidekiq:stop'
|
42
|
+
after 'deploy:reverted', 'sidekiq:stop'
|
43
|
+
after 'deploy:published', 'sidekiq:start'
|
44
|
+
end
|
45
|
+
|
33
46
|
desc "Quiet sidekiq (stop accepting new work)"
|
34
47
|
task :quiet do
|
35
48
|
on roles fetch(:sidekiq_role) do
|
@@ -86,11 +99,4 @@ namespace :sidekiq do
|
|
86
99
|
invoke 'sidekiq:start'
|
87
100
|
end
|
88
101
|
|
89
|
-
if fetch(:sidekiq_default_hooks)
|
90
|
-
after 'deploy:starting', 'sidekiq:quiet'
|
91
|
-
after 'deploy:updated', 'sidekiq:stop'
|
92
|
-
after 'deploy:reverted', 'sidekiq:stop'
|
93
|
-
after 'deploy:published', 'sidekiq:start'
|
94
|
-
end
|
95
|
-
|
96
102
|
end
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web.rb
CHANGED
@@ -73,7 +73,7 @@ module Sidekiq
|
|
73
73
|
get '/retries' do
|
74
74
|
@count = (params[:count] || 25).to_i
|
75
75
|
(@current_page, @total_size, @retries) = page("retry", params[:page], @count)
|
76
|
-
@retries = @retries.map {|msg, score|
|
76
|
+
@retries = @retries.map {|msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
77
77
|
erb :retries
|
78
78
|
end
|
79
79
|
|
@@ -125,7 +125,7 @@ module Sidekiq
|
|
125
125
|
get '/scheduled' do
|
126
126
|
@count = (params[:count] || 25).to_i
|
127
127
|
(@current_page, @total_size, @scheduled) = page("schedule", params[:page], @count)
|
128
|
-
@scheduled = @scheduled.map {|msg, score|
|
128
|
+
@scheduled = @scheduled.map {|msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
129
129
|
erb :scheduled
|
130
130
|
end
|
131
131
|
|
data/lib/sidekiq/web_helpers.rb
CHANGED
@@ -16,6 +16,10 @@ module Sidekiq
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
# This is a hook for a Sidekiq Pro feature. Please don't touch.
|
20
|
+
def filtering(*)
|
21
|
+
end
|
22
|
+
|
19
23
|
def locale
|
20
24
|
lang = (request.env["HTTP_ACCEPT_LANGUAGE"] || 'en')[0,2]
|
21
25
|
strings[lang] ? lang : 'en'
|
@@ -159,7 +163,11 @@ module Sidekiq
|
|
159
163
|
end
|
160
164
|
|
161
165
|
def h(text)
|
162
|
-
Rack::Utils.escape_html(text)
|
166
|
+
::Rack::Utils.escape_html(text)
|
167
|
+
rescue ArgumentError => e
|
168
|
+
raise unless e.message.eql?('invalid byte sequence in UTF-8')
|
169
|
+
text.encode!('UTF-16', 'UTF-8', invalid: :replace, replace: '').encode!('UTF-8', 'UTF-16')
|
170
|
+
retry
|
163
171
|
end
|
164
172
|
|
165
173
|
# Any paginated list that performs an action needs to redirect
|
data/test/config.yml
CHANGED
data/test/test_client.rb
CHANGED
@@ -168,12 +168,17 @@ class TestClient < Sidekiq::Test
|
|
168
168
|
Sidekiq::Queue.new.clear
|
169
169
|
end
|
170
170
|
it 'can push a large set of jobs at once' do
|
171
|
-
|
172
|
-
assert_equal 1_000,
|
171
|
+
jids = Sidekiq::Client.push_bulk('class' => QueuedWorker, 'args' => (1..1_000).to_a.map { |x| Array(x) })
|
172
|
+
assert_equal 1_000, jids.size
|
173
173
|
end
|
174
174
|
it 'can push a large set of jobs at once using a String class' do
|
175
|
-
|
176
|
-
assert_equal 1_000,
|
175
|
+
jids = Sidekiq::Client.push_bulk('class' => 'QueuedWorker', 'args' => (1..1_000).to_a.map { |x| Array(x) })
|
176
|
+
assert_equal 1_000, jids.size
|
177
|
+
end
|
178
|
+
it 'returns the jids for the jobs' do
|
179
|
+
Sidekiq::Client.push_bulk('class' => 'QueuedWorker', 'args' => (1..2).to_a.map { |x| Array(x) }).each do |jid|
|
180
|
+
assert_match /[0-9a-f]{12}/, jid
|
181
|
+
end
|
177
182
|
end
|
178
183
|
end
|
179
184
|
|
@@ -203,7 +208,9 @@ class TestClient < Sidekiq::Test
|
|
203
208
|
begin
|
204
209
|
assert_equal nil, Sidekiq::Client.push('class' => MyWorker, 'args' => [0])
|
205
210
|
assert_match /[0-9a-f]{12}/, Sidekiq::Client.push('class' => MyWorker, 'args' => [1])
|
206
|
-
|
211
|
+
Sidekiq::Client.push_bulk('class' => MyWorker, 'args' => [[0], [1]]).each do |jid|
|
212
|
+
assert_match /[0-9a-f]{12}/, jid
|
213
|
+
end
|
207
214
|
ensure
|
208
215
|
Sidekiq.client_middleware.remove Stopper
|
209
216
|
end
|
data/test/test_fetch.rb
CHANGED
@@ -36,7 +36,7 @@ class TestFetcher < Sidekiq::Test
|
|
36
36
|
assert_equal 0, q1.size
|
37
37
|
assert_equal 0, q2.size
|
38
38
|
uow = Sidekiq::BasicFetch::UnitOfWork
|
39
|
-
Sidekiq::BasicFetch.bulk_requeue([uow.new('fuzzy:queue:foo', 'bob'), uow.new('fuzzy:queue:foo', 'bar'), uow.new('fuzzy:queue:bar', 'widget')])
|
39
|
+
Sidekiq::BasicFetch.bulk_requeue([uow.new('fuzzy:queue:foo', 'bob'), uow.new('fuzzy:queue:foo', 'bar'), uow.new('fuzzy:queue:bar', 'widget')], {:queues => []})
|
40
40
|
assert_equal 2, q1.size
|
41
41
|
assert_equal 1, q2.size
|
42
42
|
end
|
data/test/test_manager.rb
CHANGED
@@ -29,6 +29,7 @@ class TestManager < Sidekiq::Test
|
|
29
29
|
uow.expect(:requeue, nil, [])
|
30
30
|
|
31
31
|
mgr = Sidekiq::Manager.new(options)
|
32
|
+
mgr.fetcher = Sidekiq::BasicFetch.new({:queues => []})
|
32
33
|
mgr.stop
|
33
34
|
mgr.assign(uow)
|
34
35
|
uow.verify
|
@@ -36,6 +37,7 @@ class TestManager < Sidekiq::Test
|
|
36
37
|
|
37
38
|
it 'shuts down the system' do
|
38
39
|
mgr = Sidekiq::Manager.new(options)
|
40
|
+
mgr.fetcher = Sidekiq::BasicFetch.new({:queues => []})
|
39
41
|
mgr.stop
|
40
42
|
|
41
43
|
assert mgr.busy.empty?
|
data/test/test_middleware.rb
CHANGED
@@ -82,7 +82,7 @@ class TestMiddleware < Sidekiq::Test
|
|
82
82
|
processor = Sidekiq::Processor.new(boss)
|
83
83
|
actor = Minitest::Mock.new
|
84
84
|
actor.expect(:processor_done, nil, [processor])
|
85
|
-
actor.expect(:real_thread, nil, [nil,
|
85
|
+
actor.expect(:real_thread, nil, [nil, Thread])
|
86
86
|
boss.expect(:async, actor, [])
|
87
87
|
boss.expect(:async, actor, [])
|
88
88
|
processor.process(Sidekiq::BasicFetch::UnitOfWork.new('queue:default', msg))
|
data/test/test_processor.rb
CHANGED
@@ -31,7 +31,7 @@ class TestProcessor < Sidekiq::Test
|
|
31
31
|
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
|
32
32
|
actor = Minitest::Mock.new
|
33
33
|
actor.expect(:processor_done, nil, [@processor])
|
34
|
-
actor.expect(:real_thread, nil, [nil,
|
34
|
+
actor.expect(:real_thread, nil, [nil, Thread])
|
35
35
|
@boss.expect(:async, actor, [])
|
36
36
|
@boss.expect(:async, actor, [])
|
37
37
|
@processor.process(work(msg))
|
@@ -41,7 +41,7 @@ class TestProcessor < Sidekiq::Test
|
|
41
41
|
|
42
42
|
it 'passes exceptions to ExceptionHandler' do
|
43
43
|
actor = Minitest::Mock.new
|
44
|
-
actor.expect(:real_thread, nil, [nil,
|
44
|
+
actor.expect(:real_thread, nil, [nil, Thread])
|
45
45
|
@boss.expect(:async, actor, [])
|
46
46
|
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
|
47
47
|
begin
|
@@ -57,7 +57,7 @@ class TestProcessor < Sidekiq::Test
|
|
57
57
|
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
|
58
58
|
re_raise = false
|
59
59
|
actor = Minitest::Mock.new
|
60
|
-
actor.expect(:real_thread, nil, [nil,
|
60
|
+
actor.expect(:real_thread, nil, [nil, Thread])
|
61
61
|
@boss.expect(:async, actor, [])
|
62
62
|
|
63
63
|
begin
|
@@ -75,7 +75,7 @@ class TestProcessor < Sidekiq::Test
|
|
75
75
|
processor = ::Sidekiq::Processor.new(@boss)
|
76
76
|
actor = Minitest::Mock.new
|
77
77
|
actor.expect(:processor_done, nil, [processor])
|
78
|
-
actor.expect(:real_thread, nil, [nil,
|
78
|
+
actor.expect(:real_thread, nil, [nil, Thread])
|
79
79
|
@boss.expect(:async, actor, [])
|
80
80
|
@boss.expect(:async, actor, [])
|
81
81
|
processor.process(work(msgstr))
|
@@ -103,7 +103,7 @@ class TestProcessor < Sidekiq::Test
|
|
103
103
|
def successful_job
|
104
104
|
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
|
105
105
|
actor = Minitest::Mock.new
|
106
|
-
actor.expect(:real_thread, nil, [nil,
|
106
|
+
actor.expect(:real_thread, nil, [nil, Thread])
|
107
107
|
actor.expect(:processor_done, nil, [@processor])
|
108
108
|
@boss.expect(:async, actor, [])
|
109
109
|
@boss.expect(:async, actor, [])
|
@@ -131,7 +131,7 @@ class TestProcessor < Sidekiq::Test
|
|
131
131
|
|
132
132
|
def failed_job
|
133
133
|
actor = Minitest::Mock.new
|
134
|
-
actor.expect(:real_thread, nil, [nil,
|
134
|
+
actor.expect(:real_thread, nil, [nil, Thread])
|
135
135
|
@boss.expect(:async, actor, [])
|
136
136
|
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
|
137
137
|
begin
|
@@ -87,6 +87,20 @@ class TestRedisConnection < Sidekiq::Test
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
+
describe "with REDISTOGO_URL and a parallel REDIS_PROVIDER set" do
|
91
|
+
it "sets connection URI to the provider" do
|
92
|
+
uri = 'redis://sidekiq-redis-provider:6379/0'
|
93
|
+
provider = 'SIDEKIQ_REDIS_PROVIDER'
|
94
|
+
|
95
|
+
ENV['REDIS_PROVIDER'] = provider
|
96
|
+
ENV[provider] = uri
|
97
|
+
ENV['REDISTOGO_URL'] = 'redis://redis-to-go:6379/0'
|
98
|
+
with_env_var provider, uri, true
|
99
|
+
|
100
|
+
ENV[provider] = nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
90
104
|
describe "with REDIS_PROVIDER set" do
|
91
105
|
it "sets connection URI to the provider" do
|
92
106
|
uri = 'redis://sidekiq-redis-provider:6379/0'
|
data/test/test_scheduling.rb
CHANGED
@@ -31,7 +31,7 @@ class TestScheduling < Sidekiq::Test
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'schedules job right away on negative timestamp/interval' do
|
34
|
-
@redis.expect :sadd, true, ['queues',
|
34
|
+
@redis.expect :sadd, true, ['queues', 'custom_queue']
|
35
35
|
@redis.expect :lpush, true, ['queue:custom_queue', Array]
|
36
36
|
assert ScheduledWorker.perform_in(-300, 'mike')
|
37
37
|
@redis.verify
|
@@ -188,6 +188,17 @@ td form {
|
|
188
188
|
margin-bottom: 0;
|
189
189
|
}
|
190
190
|
|
191
|
+
td.table-checkbox {
|
192
|
+
padding: 0px;
|
193
|
+
}
|
194
|
+
|
195
|
+
td.table-checkbox label {
|
196
|
+
height: 100%;
|
197
|
+
width: 100%;
|
198
|
+
padding: 8px;
|
199
|
+
margin-bottom: 0;
|
200
|
+
}
|
201
|
+
|
191
202
|
.navbar .navbar-brand {
|
192
203
|
color: #b1003e;
|
193
204
|
padding: 13px;
|
data/web/views/retries.erb
CHANGED
@@ -2,11 +2,12 @@
|
|
2
2
|
<div class="col-sm-5">
|
3
3
|
<h3><%= t('Retries') %></h3>
|
4
4
|
</div>
|
5
|
-
|
6
|
-
|
5
|
+
<% if @retries.size > 0 && @total_size > @count %>
|
6
|
+
<div class="col-sm-4">
|
7
7
|
<%= erb :_paging, :locals => { :url => "#{root_path}retries" } %>
|
8
|
-
|
9
|
-
|
8
|
+
</div>
|
9
|
+
<% end %>
|
10
|
+
<%= filtering('retries') %>
|
10
11
|
</header>
|
11
12
|
|
12
13
|
<% if @retries.size > 0 %>
|
@@ -25,24 +26,26 @@
|
|
25
26
|
<th><%= t('Error') %></th>
|
26
27
|
</tr>
|
27
28
|
</thead>
|
28
|
-
<% @retries.each do |
|
29
|
+
<% @retries.each do |entry| %>
|
29
30
|
<tr>
|
30
|
-
<td>
|
31
|
-
<
|
31
|
+
<td class="table-checkbox">
|
32
|
+
<label>
|
33
|
+
<input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' />
|
34
|
+
</label>
|
32
35
|
</td>
|
33
36
|
<td>
|
34
|
-
<a href="<%= root_path %>retries/<%= job_params(
|
37
|
+
<a href="<%= root_path %>retries/<%= job_params(entry.item, entry.score) %>"><%= relative_time(entry.at) %></a>
|
35
38
|
</td>
|
36
|
-
<td><%=
|
39
|
+
<td><%= entry['retry_count'] %></td>
|
37
40
|
<td>
|
38
|
-
<a href="<%= root_path %>queues/<%=
|
41
|
+
<a href="<%= root_path %>queues/<%= entry.queue %>"><%= entry.queue %></a>
|
39
42
|
</td>
|
40
|
-
<td><%=
|
43
|
+
<td><%= entry.klass %></td>
|
41
44
|
<td>
|
42
|
-
<div class="args"><%= display_args(
|
45
|
+
<div class="args"><%= display_args(entry.args) %></div>
|
43
46
|
</td>
|
44
47
|
<td>
|
45
|
-
<div><%= h truncate("#{
|
48
|
+
<div><%= h truncate("#{entry['error_class']}: #{entry['error_message']}", 200) %></div>
|
46
49
|
</td>
|
47
50
|
</tr>
|
48
51
|
<% end %>
|
data/web/views/scheduled.erb
CHANGED
@@ -2,11 +2,12 @@
|
|
2
2
|
<div class="col-sm-5">
|
3
3
|
<h3><%= t('ScheduledJobs') %></h3>
|
4
4
|
</div>
|
5
|
-
|
6
|
-
|
5
|
+
<% if @scheduled.size > 0 && @total_size > @count %>
|
6
|
+
<div class="col-sm-4">
|
7
7
|
<%= erb :_paging, :locals => { :url => "#{root_path}scheduled" } %>
|
8
|
-
|
9
|
-
|
8
|
+
</div>
|
9
|
+
<% end %>
|
10
|
+
<%= filtering('scheduled') %>
|
10
11
|
</header>
|
11
12
|
|
12
13
|
<% if @scheduled.size > 0 %>
|
@@ -24,20 +25,20 @@
|
|
24
25
|
<th><%= t('Arguments') %></th>
|
25
26
|
</tr>
|
26
27
|
</thead>
|
27
|
-
<% @scheduled.each do |
|
28
|
+
<% @scheduled.each do |entry| %>
|
28
29
|
<tr>
|
29
30
|
<td>
|
30
|
-
<input type='checkbox' name='key[]' value='<%= job_params(
|
31
|
+
<input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' />
|
31
32
|
</td>
|
32
33
|
<td>
|
33
|
-
<a href="<%= root_path %>scheduled/<%= job_params(
|
34
|
+
<a href="<%= root_path %>scheduled/<%= job_params(entry.item, entry.score) %>"><%= relative_time(entry.at) %></a>
|
34
35
|
</td>
|
35
36
|
<td>
|
36
|
-
<a href="<%= root_path %>queues/<%=
|
37
|
+
<a href="<%= root_path %>queues/<%= entry.queue %>"><%= entry.queue %></a>
|
37
38
|
</td>
|
38
|
-
<td><%=
|
39
|
+
<td><%= entry.klass %></td>
|
39
40
|
<td>
|
40
|
-
<div class="args"><%= display_args(
|
41
|
+
<div class="args"><%= display_args(entry.args) %></div>
|
41
42
|
</td>
|
42
43
|
</tr>
|
43
44
|
<% end %>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Perham
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-11-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -352,7 +352,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
352
352
|
version: '0'
|
353
353
|
requirements: []
|
354
354
|
rubyforge_project:
|
355
|
-
rubygems_version: 2.
|
355
|
+
rubygems_version: 2.1.9
|
356
356
|
signing_key:
|
357
357
|
specification_version: 4
|
358
358
|
summary: Simple, efficient background processing for Ruby
|