sidekiq 2.17.8 → 3.0.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/3.0-Upgrade.md +63 -0
- data/Changes.md +66 -3
- data/Contributing.md +1 -3
- data/Pro-Changes.md +18 -0
- data/README.md +2 -2
- data/bin/sidekiqctl +19 -6
- data/lib/sidekiq.rb +53 -11
- data/lib/sidekiq/actor.rb +1 -0
- data/lib/sidekiq/api.rb +145 -58
- data/lib/sidekiq/cli.rb +22 -18
- data/lib/sidekiq/client.rb +44 -14
- data/lib/sidekiq/core_ext.rb +5 -8
- data/lib/sidekiq/exception_handler.rb +19 -28
- data/lib/sidekiq/fetch.rb +3 -3
- data/lib/sidekiq/launcher.rb +30 -3
- data/lib/sidekiq/logging.rb +2 -2
- data/lib/sidekiq/manager.rb +19 -16
- data/lib/sidekiq/middleware/chain.rb +1 -1
- data/lib/sidekiq/middleware/i18n.rb +1 -1
- data/lib/sidekiq/middleware/server/retry_jobs.rb +23 -7
- data/lib/sidekiq/processor.rb +36 -54
- data/lib/sidekiq/redis_connection.rb +1 -3
- data/lib/sidekiq/util.rb +4 -4
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +57 -8
- data/lib/sidekiq/web_helpers.rb +6 -15
- data/lib/sidekiq/worker.rb +3 -1
- data/sidekiq.gemspec +5 -5
- data/test/test_api.rb +59 -19
- data/test/test_cli.rb +1 -1
- data/test/test_client.rb +44 -5
- data/test/test_exception_handler.rb +4 -87
- data/test/test_middleware.rb +3 -2
- data/test/test_redis_connection.rb +0 -6
- data/test/test_retry.rb +13 -68
- data/test/test_scheduled.rb +1 -1
- data/test/test_scheduling.rb +5 -0
- data/test/test_sidekiq.rb +18 -0
- data/test/test_web.rb +98 -58
- data/web/assets/stylesheets/application.css +5 -0
- data/web/locales/cs.yml +68 -0
- data/web/locales/da.yml +9 -1
- data/web/locales/de.yml +15 -7
- data/web/locales/el.yml +68 -0
- data/web/locales/en.yml +8 -3
- data/web/locales/es.yml +9 -1
- data/web/locales/fr.yml +34 -26
- data/web/locales/it.yml +26 -18
- data/web/locales/ja.yml +8 -2
- data/web/locales/ko.yml +0 -2
- data/web/locales/nl.yml +8 -3
- data/web/locales/no.yml +9 -3
- data/web/locales/pl.yml +0 -1
- data/web/locales/pt-br.yml +11 -4
- data/web/locales/pt.yml +8 -1
- data/web/locales/ru.yml +29 -22
- data/web/locales/sv.yml +68 -0
- data/web/locales/zh-tw.yml +68 -0
- data/web/views/_job_info.erb +8 -2
- data/web/views/_summary.erb +13 -7
- data/web/views/busy.erb +55 -0
- data/web/views/dead.erb +30 -0
- data/web/views/layout.erb +1 -0
- data/web/views/morgue.erb +66 -0
- metadata +29 -30
- data/config.ru +0 -18
- data/lib/sidekiq/capistrano.rb +0 -5
- data/lib/sidekiq/capistrano2.rb +0 -54
- data/lib/sidekiq/tasks/sidekiq.rake +0 -119
- data/lib/sidekiq/yaml_patch.rb +0 -21
- data/test/test_util.rb +0 -18
- data/web/views/_workers.erb +0 -22
- data/web/views/workers.erb +0 -16
data/lib/sidekiq/processor.rb
CHANGED
@@ -11,7 +11,9 @@ module Sidekiq
|
|
11
11
|
# processes it. It instantiates the worker, runs the middleware
|
12
12
|
# chain and then calls Sidekiq::Worker#perform.
|
13
13
|
class Processor
|
14
|
-
|
14
|
+
# To prevent a memory leak, ensure that stats expire. However, they should take up a minimal amount of storage
|
15
|
+
# so keep them around for a long time
|
16
|
+
STATS_TIMEOUT = 24 * 60 * 60 * 365 * 5
|
15
17
|
|
16
18
|
include Util
|
17
19
|
include Actor
|
@@ -34,32 +36,30 @@ module Sidekiq
|
|
34
36
|
msgstr = work.message
|
35
37
|
queue = work.queue_name
|
36
38
|
|
37
|
-
|
38
|
-
@boss.async.real_thread(proxy_id, Thread.current)
|
39
|
+
@boss.async.real_thread(proxy_id, Thread.current)
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
41
|
+
ack = true
|
42
|
+
begin
|
43
|
+
msg = Sidekiq.load_json(msgstr)
|
44
|
+
klass = msg['class'].constantize
|
45
|
+
worker = klass.new
|
46
|
+
worker.jid = msg['jid']
|
47
|
+
|
48
|
+
stats(worker, msg, queue) do
|
49
|
+
Sidekiq.server_middleware.invoke(worker, msg, queue) do
|
50
|
+
worker.perform(*cloned(msg['args']))
|
51
51
|
end
|
52
|
-
rescue Sidekiq::Shutdown
|
53
|
-
# Had to force kill this job because it didn't finish
|
54
|
-
# within the timeout. Don't acknowledge the work since
|
55
|
-
# we didn't properly finish it.
|
56
|
-
ack = false
|
57
|
-
rescue Exception => ex
|
58
|
-
handle_exception(ex, msg || { :message => msgstr })
|
59
|
-
raise
|
60
|
-
ensure
|
61
|
-
work.acknowledge if ack
|
62
52
|
end
|
53
|
+
rescue Sidekiq::Shutdown
|
54
|
+
# Had to force kill this job because it didn't finish
|
55
|
+
# within the timeout. Don't acknowledge the work since
|
56
|
+
# we didn't properly finish it.
|
57
|
+
ack = false
|
58
|
+
rescue Exception => ex
|
59
|
+
handle_exception(ex, msg || { :message => msgstr })
|
60
|
+
raise
|
61
|
+
ensure
|
62
|
+
work.acknowledge if ack
|
63
63
|
end
|
64
64
|
|
65
65
|
@boss.async.processor_done(current_actor)
|
@@ -71,35 +71,19 @@ module Sidekiq
|
|
71
71
|
|
72
72
|
private
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
#
|
77
|
-
# For some reason, Celluloid's thread dispatch, TaskThread,
|
78
|
-
# is unstable under heavy concurrency but TaskFiber has proven
|
79
|
-
# itself stable.
|
80
|
-
NEED_DEFER = (RUBY_ENGINE == 'ruby' && RUBY_VERSION < '2.0.0')
|
81
|
-
|
82
|
-
def do_defer(&block)
|
83
|
-
if NEED_DEFER
|
84
|
-
defer(&block)
|
85
|
-
else
|
86
|
-
yield
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def identity
|
91
|
-
@str ||= "#{hostname}:#{process_id}-#{Thread.current.object_id}:default"
|
74
|
+
def thread_identity
|
75
|
+
@str ||= Thread.current.object_id.to_s(36)
|
92
76
|
end
|
93
77
|
|
94
78
|
def stats(worker, msg, queue)
|
95
|
-
# Do not conflate errors from the job with errors caused by updating
|
79
|
+
# Do not conflate errors from the job with errors caused by updating
|
80
|
+
# stats so calling code can react appropriately
|
96
81
|
retry_and_suppress_exceptions do
|
97
|
-
|
82
|
+
hash = Sidekiq.dump_json({:queue => queue, :payload => msg, :run_at => Time.now.to_i })
|
83
|
+
Sidekiq.redis do |conn|
|
98
84
|
conn.multi do
|
99
|
-
conn.
|
100
|
-
conn.
|
101
|
-
hash = {:queue => queue, :payload => msg, :run_at => Time.now.to_i }
|
102
|
-
conn.setex("worker:#{identity}", EXPIRY, Sidekiq.dump_json(hash))
|
85
|
+
conn.hmset("#{identity}:workers", thread_identity, hash)
|
86
|
+
conn.expire("#{identity}:workers", 60*60)
|
103
87
|
end
|
104
88
|
end
|
105
89
|
end
|
@@ -108,7 +92,7 @@ module Sidekiq
|
|
108
92
|
yield
|
109
93
|
rescue Exception
|
110
94
|
retry_and_suppress_exceptions do
|
111
|
-
redis do |conn|
|
95
|
+
Sidekiq.redis do |conn|
|
112
96
|
failed = "stat:failed:#{Time.now.utc.to_date}"
|
113
97
|
result = conn.multi do
|
114
98
|
conn.incrby("stat:failed", 1)
|
@@ -120,12 +104,10 @@ module Sidekiq
|
|
120
104
|
raise
|
121
105
|
ensure
|
122
106
|
retry_and_suppress_exceptions do
|
123
|
-
redis do |conn|
|
107
|
+
Sidekiq.redis do |conn|
|
124
108
|
processed = "stat:processed:#{Time.now.utc.to_date}"
|
125
109
|
result = conn.multi do
|
126
|
-
conn.
|
127
|
-
conn.del("worker:#{identity}")
|
128
|
-
conn.del("worker:#{identity}:started")
|
110
|
+
conn.hdel("#{identity}:workers", thread_identity)
|
129
111
|
conn.incrby("stat:processed", 1)
|
130
112
|
conn.incrby(processed, 1)
|
131
113
|
end
|
@@ -158,7 +140,7 @@ module Sidekiq
|
|
158
140
|
sleep(1)
|
159
141
|
retry
|
160
142
|
else
|
161
|
-
|
143
|
+
handle_exception(e, { :message => "Exhausted #{max_retries} retries"})
|
162
144
|
end
|
163
145
|
end
|
164
146
|
end
|
@@ -68,9 +68,7 @@ module Sidekiq
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def determine_redis_provider
|
71
|
-
|
72
|
-
provider = ENV['REDIS_PROVIDER'] || 'REDIS_URL'
|
73
|
-
ENV[provider] || ENV['REDISTOGO_URL']
|
71
|
+
ENV[ENV['REDIS_PROVIDER'] || 'REDIS_URL']
|
74
72
|
end
|
75
73
|
|
76
74
|
end
|
data/lib/sidekiq/util.rb
CHANGED
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web.rb
CHANGED
@@ -20,10 +20,11 @@ module Sidekiq
|
|
20
20
|
|
21
21
|
DEFAULT_TABS = {
|
22
22
|
"Dashboard" => '',
|
23
|
-
"
|
23
|
+
"Busy" => 'busy',
|
24
24
|
"Queues" => 'queues',
|
25
25
|
"Retries" => 'retries',
|
26
26
|
"Scheduled" => 'scheduled',
|
27
|
+
"Dead" => 'morgue',
|
27
28
|
}
|
28
29
|
|
29
30
|
class << self
|
@@ -37,8 +38,8 @@ module Sidekiq
|
|
37
38
|
alias_method :tabs, :custom_tabs
|
38
39
|
end
|
39
40
|
|
40
|
-
get "/
|
41
|
-
erb :
|
41
|
+
get "/busy" do
|
42
|
+
erb :busy
|
42
43
|
end
|
43
44
|
|
44
45
|
get "/queues" do
|
@@ -55,11 +56,6 @@ module Sidekiq
|
|
55
56
|
erb :queue
|
56
57
|
end
|
57
58
|
|
58
|
-
post "/reset" do
|
59
|
-
reset_worker_list
|
60
|
-
redirect root_path
|
61
|
-
end
|
62
|
-
|
63
59
|
post "/queues/:name" do
|
64
60
|
Sidekiq::Queue.new(params[:name]).clear
|
65
61
|
redirect "#{root_path}queues"
|
@@ -70,6 +66,59 @@ module Sidekiq
|
|
70
66
|
redirect_with_query("#{root_path}queues/#{params[:name]}")
|
71
67
|
end
|
72
68
|
|
69
|
+
get '/morgue' do
|
70
|
+
@count = (params[:count] || 25).to_i
|
71
|
+
(@current_page, @total_size, @dead) = page("dead", params[:page], @count)
|
72
|
+
@dead = @dead.map {|msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
73
|
+
erb :morgue
|
74
|
+
end
|
75
|
+
|
76
|
+
get "/morgue/:key" do
|
77
|
+
halt 404 unless params['key']
|
78
|
+
@dead = Sidekiq::DeadSet.new.fetch(*parse_params(params['key'])).first
|
79
|
+
redirect "#{root_path}morgue" if @dead.nil?
|
80
|
+
erb :dead
|
81
|
+
end
|
82
|
+
|
83
|
+
post '/morgue' do
|
84
|
+
halt 404 unless params['key']
|
85
|
+
|
86
|
+
params['key'].each do |key|
|
87
|
+
job = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
|
88
|
+
next unless job
|
89
|
+
if params['retry']
|
90
|
+
job.retry
|
91
|
+
elsif params['delete']
|
92
|
+
job.delete
|
93
|
+
end
|
94
|
+
end
|
95
|
+
redirect_with_query("#{root_path}morgue")
|
96
|
+
end
|
97
|
+
|
98
|
+
post "/morgue/all/delete" do
|
99
|
+
Sidekiq::DeadSet.new.clear
|
100
|
+
redirect "#{root_path}morgue"
|
101
|
+
end
|
102
|
+
|
103
|
+
post "/morgue/all/retry" do
|
104
|
+
Sidekiq::DeadSet.new.retry_all
|
105
|
+
redirect "#{root_path}morgue"
|
106
|
+
end
|
107
|
+
|
108
|
+
post "/morgue/:key" do
|
109
|
+
halt 404 unless params['key']
|
110
|
+
job = Sidekiq::DeadSet.new.fetch(*parse_params(params['key'])).first
|
111
|
+
if job
|
112
|
+
if params['retry']
|
113
|
+
job.retry
|
114
|
+
elsif params['delete']
|
115
|
+
job.delete
|
116
|
+
end
|
117
|
+
end
|
118
|
+
redirect_with_query("#{root_path}morgue")
|
119
|
+
end
|
120
|
+
|
121
|
+
|
73
122
|
get '/retries' do
|
74
123
|
@count = (params[:count] || 25).to_i
|
75
124
|
(@current_page, @total_size, @retries) = page("retry", params[:page], @count)
|
data/lib/sidekiq/web_helpers.rb
CHANGED
@@ -31,28 +31,19 @@ module Sidekiq
|
|
31
31
|
|
32
32
|
def t(msg, options={})
|
33
33
|
string = get_locale[msg] || msg
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
Sidekiq.redis do |conn|
|
39
|
-
workers = conn.smembers('workers')
|
40
|
-
conn.srem('workers', workers) if !workers.empty?
|
34
|
+
if options.empty?
|
35
|
+
string
|
36
|
+
else
|
37
|
+
string % options
|
41
38
|
end
|
42
39
|
end
|
43
40
|
|
44
41
|
def workers_size
|
45
|
-
@workers_size ||=
|
46
|
-
conn.scard('workers')
|
47
|
-
end
|
42
|
+
@workers_size ||= workers.size
|
48
43
|
end
|
49
44
|
|
50
45
|
def workers
|
51
|
-
@workers ||=
|
52
|
-
Sidekiq::Workers.new.tap do |w|
|
53
|
-
w.prune
|
54
|
-
end
|
55
|
-
end
|
46
|
+
@workers ||= Sidekiq::Workers.new
|
56
47
|
end
|
57
48
|
|
58
49
|
def stats
|
data/lib/sidekiq/worker.rb
CHANGED
@@ -62,6 +62,7 @@ module Sidekiq
|
|
62
62
|
# :retry - enable the RetryJobs middleware for this Worker, default *true*
|
63
63
|
# :backtrace - whether to save any error backtrace in the retry payload to display in web UI,
|
64
64
|
# can be true, false or an integer number of lines to save, default *false*
|
65
|
+
# :pool - use the given Redis connection pool to push this type of job to a given shard.
|
65
66
|
def sidekiq_options(opts={})
|
66
67
|
self.sidekiq_options_hash = get_sidekiq_options.merge((opts || {}).stringify_keys)
|
67
68
|
::Sidekiq.logger.warn("#{self.name} - :timeout is unsafe and support has been removed from Sidekiq, see http://bit.ly/OtYpK for details") if opts.include? :timeout
|
@@ -80,7 +81,8 @@ module Sidekiq
|
|
80
81
|
end
|
81
82
|
|
82
83
|
def client_push(item) # :nodoc:
|
83
|
-
Sidekiq
|
84
|
+
pool = Thread.current[:sidekiq_via_pool] || get_sidekiq_options['pool'] || Sidekiq.redis_pool
|
85
|
+
Sidekiq::Client.new(pool).push(item.stringify_keys)
|
84
86
|
end
|
85
87
|
|
86
88
|
end
|
data/sidekiq.gemspec
CHANGED
@@ -14,14 +14,14 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.name = "sidekiq"
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = Sidekiq::VERSION
|
17
|
-
gem.add_dependency 'redis', '
|
18
|
-
gem.add_dependency 'redis-namespace', '
|
19
|
-
gem.add_dependency 'connection_pool', '
|
20
|
-
gem.add_dependency 'celluloid', '0.15.2'
|
17
|
+
gem.add_dependency 'redis', '>= 3.0.6'
|
18
|
+
gem.add_dependency 'redis-namespace', '>= 1.3.1'
|
19
|
+
gem.add_dependency 'connection_pool', '>= 2.0.0'
|
20
|
+
gem.add_dependency 'celluloid', '>= 0.15.2'
|
21
21
|
gem.add_dependency 'json'
|
22
22
|
gem.add_development_dependency 'sinatra'
|
23
23
|
gem.add_development_dependency 'minitest', '~> 4.2'
|
24
24
|
gem.add_development_dependency 'rake'
|
25
|
-
gem.add_development_dependency 'rails', '4.0.
|
25
|
+
gem.add_development_dependency 'rails', '>= 4.0.0'
|
26
26
|
gem.add_development_dependency 'coveralls'
|
27
27
|
end
|
data/test/test_api.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
class TestApi < Sidekiq::Test
|
4
|
+
|
4
5
|
describe "stats" do
|
5
6
|
before do
|
6
7
|
Sidekiq.redis {|c| c.flushdb }
|
@@ -160,6 +161,8 @@ class TestApi < Sidekiq::Test
|
|
160
161
|
end
|
161
162
|
|
162
163
|
describe 'with an empty database' do
|
164
|
+
include Sidekiq::Util
|
165
|
+
|
163
166
|
before do
|
164
167
|
Sidekiq.redis {|c| c.flushdb }
|
165
168
|
end
|
@@ -339,6 +342,23 @@ class TestApi < Sidekiq::Test
|
|
339
342
|
assert_equal 0, r.size
|
340
343
|
end
|
341
344
|
|
345
|
+
it 'can enumerate processes' do
|
346
|
+
odata = { 'pid' => 123, 'hostname' => hostname, 'key' => "#{hostname}:123", 'started_at' => Time.now.to_f - 15 }
|
347
|
+
time = Time.now.to_f
|
348
|
+
Sidekiq.redis do |conn|
|
349
|
+
conn.multi do
|
350
|
+
conn.sadd('processes', odata['key'])
|
351
|
+
conn.hmset(odata['key'], 'info', Sidekiq.dump_json(odata), 'busy', 10, 'beat', time)
|
352
|
+
conn.sadd('processes', 'fake:pid')
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
ps = Sidekiq::ProcessSet.new.to_a
|
357
|
+
assert_equal 1, ps.size
|
358
|
+
data = ps.first
|
359
|
+
assert_equal odata.merge('busy' => 10, 'beat' => time), data
|
360
|
+
end
|
361
|
+
|
342
362
|
it 'can enumerate workers' do
|
343
363
|
w = Sidekiq::Workers.new
|
344
364
|
assert_equal 0, w.size
|
@@ -346,38 +366,36 @@ class TestApi < Sidekiq::Test
|
|
346
366
|
assert false
|
347
367
|
end
|
348
368
|
|
349
|
-
|
369
|
+
key = "#{hostname}:#{$$}"
|
370
|
+
pdata = { 'pid' => $$, 'hostname' => hostname, 'started_at' => Time.now.to_i }
|
371
|
+
Sidekiq.redis do |conn|
|
372
|
+
conn.sadd('processes', key)
|
373
|
+
conn.hmset(key, 'info', Sidekiq.dump_json(pdata), 'busy', 0, 'beat', Time.now.to_f)
|
374
|
+
end
|
375
|
+
|
376
|
+
s = "#{key}:workers"
|
350
377
|
data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => Time.now.to_i })
|
351
378
|
Sidekiq.redis do |c|
|
352
|
-
c.
|
353
|
-
c.sadd('workers', s)
|
354
|
-
c.set("worker:#{s}", data)
|
355
|
-
c.set("worker:#{s}:started", Time.now.to_s)
|
356
|
-
end
|
379
|
+
c.hmset(s, '1234', data)
|
357
380
|
end
|
358
381
|
|
359
|
-
|
360
|
-
|
361
|
-
assert_equal
|
382
|
+
w.each do |p, x, y|
|
383
|
+
assert_equal key, p
|
384
|
+
assert_equal "1234", x
|
362
385
|
assert_equal 'default', y['queue']
|
363
|
-
assert_equal Time.now.year,
|
386
|
+
assert_equal Time.now.year, Time.at(y['run_at']).year
|
364
387
|
end
|
365
388
|
|
366
|
-
s =
|
389
|
+
s = "#{key}:workers"
|
367
390
|
data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => (Time.now.to_i - 2*60*60) })
|
368
391
|
Sidekiq.redis do |c|
|
369
392
|
c.multi do
|
370
|
-
c.
|
371
|
-
c.
|
372
|
-
c.set("worker:#{s}:started", Time.now.to_s)
|
373
|
-
c.sadd('workers', '123457')
|
393
|
+
c.hmset(s, '5678', data)
|
394
|
+
c.hmset("b#{s}", '5678', data)
|
374
395
|
end
|
375
396
|
end
|
376
397
|
|
377
|
-
assert_equal
|
378
|
-
count = w.prune
|
379
|
-
assert_equal 1, w.size
|
380
|
-
assert_equal 2, count
|
398
|
+
assert_equal ['1234', '5678'], w.map { |_, tid, _| tid }
|
381
399
|
end
|
382
400
|
|
383
401
|
it 'can reschedule jobs' do
|
@@ -396,6 +414,28 @@ class TestApi < Sidekiq::Test
|
|
396
414
|
assert(retries.map { |r| r.score > (Time.now.to_f + 9) }.any?)
|
397
415
|
end
|
398
416
|
|
417
|
+
it 'prunes processes which have died' do
|
418
|
+
data = { 'pid' => rand(10_000), 'hostname' => "app#{rand(1_000)}", 'started_at' => Time.now.to_f }
|
419
|
+
key = "#{data['hostname']}:#{data['pid']}"
|
420
|
+
Sidekiq.redis do |conn|
|
421
|
+
conn.sadd('processes', key)
|
422
|
+
conn.hmset(key, 'info', Sidekiq.dump_json(data), 'busy', 0, 'beat', Time.now.to_f)
|
423
|
+
end
|
424
|
+
|
425
|
+
ps = Sidekiq::ProcessSet.new
|
426
|
+
assert_equal 1, ps.size
|
427
|
+
assert_equal 1, ps.to_a.size
|
428
|
+
|
429
|
+
Sidekiq.redis do |conn|
|
430
|
+
conn.sadd('processes', "bar:987")
|
431
|
+
conn.sadd('processes', "bar:986")
|
432
|
+
end
|
433
|
+
|
434
|
+
ps = Sidekiq::ProcessSet.new
|
435
|
+
assert_equal 3, ps.size
|
436
|
+
assert_equal 1, ps.to_a.size
|
437
|
+
end
|
438
|
+
|
399
439
|
def add_retry(jid = 'bob', at = Time.now.to_f)
|
400
440
|
payload = Sidekiq.dump_json('class' => 'ApiWorker', 'args' => [1, 'mike'], 'queue' => 'default', 'jid' => jid, 'retry_count' => 2, 'failed_at' => Time.now.to_f)
|
401
441
|
Sidekiq.redis do |conn|
|