sidekiq 3.4.1 → 4.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/4.0-Upgrade.md +50 -0
- data/COMM-LICENSE +55 -45
- data/Changes.md +73 -1
- data/Ent-Changes.md +66 -0
- data/Gemfile +7 -1
- data/Pro-2.0-Upgrade.md +2 -2
- data/Pro-3.0-Upgrade.md +46 -0
- data/Pro-Changes.md +65 -2
- data/README.md +8 -9
- data/bin/sidekiq +5 -0
- data/bin/sidekiqctl +8 -2
- data/bin/sidekiqload +167 -0
- data/lib/sidekiq/api.rb +29 -31
- data/lib/sidekiq/cli.rb +41 -42
- data/lib/sidekiq/client.rb +5 -10
- data/lib/sidekiq/fetch.rb +35 -111
- data/lib/sidekiq/launcher.rb +102 -42
- data/lib/sidekiq/manager.rb +78 -180
- data/lib/sidekiq/middleware/server/logging.rb +10 -5
- data/lib/sidekiq/middleware/server/retry_jobs.rb +5 -5
- data/lib/sidekiq/processor.rb +126 -97
- data/lib/sidekiq/redis_connection.rb +23 -5
- data/lib/sidekiq/scheduled.rb +47 -26
- data/lib/sidekiq/testing.rb +96 -17
- data/lib/sidekiq/util.rb +20 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +17 -1
- data/lib/sidekiq/web_helpers.rb +26 -4
- data/lib/sidekiq/worker.rb +14 -0
- data/lib/sidekiq.rb +37 -14
- data/sidekiq.gemspec +11 -11
- data/test/helper.rb +45 -10
- data/test/test_actors.rb +137 -0
- data/test/test_api.rb +388 -388
- data/test/test_cli.rb +29 -59
- data/test/test_client.rb +60 -135
- data/test/test_extensions.rb +29 -23
- data/test/test_fetch.rb +2 -57
- data/test/test_launcher.rb +80 -0
- data/test/test_logging.rb +1 -1
- data/test/test_manager.rb +16 -131
- data/test/test_middleware.rb +3 -5
- data/test/test_processor.rb +110 -76
- data/test/test_rails.rb +21 -0
- data/test/test_redis_connection.rb +0 -1
- data/test/test_retry.rb +114 -162
- data/test/test_scheduled.rb +11 -17
- data/test/test_scheduling.rb +20 -42
- data/test/test_sidekiq.rb +46 -16
- data/test/test_testing.rb +80 -20
- data/test/test_testing_fake.rb +68 -8
- data/test/test_testing_inline.rb +3 -3
- data/test/test_util.rb +16 -0
- data/test/test_web.rb +17 -3
- data/test/test_web_helpers.rb +3 -2
- data/web/assets/images/favicon.ico +0 -0
- data/web/assets/javascripts/application.js +6 -1
- data/web/assets/javascripts/dashboard.js +2 -8
- data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +14 -14
- data/web/assets/stylesheets/application.css +33 -56
- data/web/locales/de.yml +1 -1
- data/web/locales/en.yml +1 -0
- data/web/locales/{no.yml → nb.yml} +10 -2
- data/web/locales/uk.yml +76 -0
- data/web/views/_footer.erb +2 -7
- data/web/views/_job_info.erb +1 -1
- data/web/views/_nav.erb +2 -2
- data/web/views/_poll_js.erb +5 -0
- data/web/views/{_poll.erb → _poll_link.erb} +0 -3
- data/web/views/busy.erb +2 -1
- data/web/views/dead.erb +1 -0
- data/web/views/layout.erb +2 -0
- data/web/views/morgue.erb +3 -0
- data/web/views/queue.erb +1 -0
- data/web/views/queues.erb +1 -0
- data/web/views/retries.erb +3 -0
- data/web/views/retry.erb +1 -0
- data/web/views/scheduled.erb +1 -0
- data/web/views/scheduled_job_info.erb +1 -0
- metadata +81 -47
- data/lib/sidekiq/actor.rb +0 -39
- data/test/test_worker_generator.rb +0 -17
data/lib/sidekiq/util.rb
CHANGED
@@ -19,6 +19,12 @@ module Sidekiq
|
|
19
19
|
raise ex
|
20
20
|
end
|
21
21
|
|
22
|
+
def safe_thread(name, &block)
|
23
|
+
Thread.new do
|
24
|
+
watchdog(name, &block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
22
28
|
def logger
|
23
29
|
Sidekiq.logger
|
24
30
|
end
|
@@ -49,6 +55,20 @@ module Sidekiq
|
|
49
55
|
handle_exception(ex, { event: event })
|
50
56
|
end
|
51
57
|
end
|
58
|
+
arr.clear
|
59
|
+
end
|
60
|
+
|
61
|
+
def want_a_hertz_donut?
|
62
|
+
# what's a hertz donut?
|
63
|
+
# punch! Hurts, don't it?
|
64
|
+
info = Sidekiq.redis {|c| c.info }
|
65
|
+
if info['connected_clients'].to_i > 1000 && info['hz'].to_i >= 10
|
66
|
+
Sidekiq.logger.warn { "Your Redis `hz` setting is too high at #{info['hz']}. See mperham/sidekiq#2431. Set it to 3 in #{info[:config_file]}" }
|
67
|
+
true
|
68
|
+
else
|
69
|
+
Sidekiq.logger.debug { "Redis hz: #{info['hz']}. Client count: #{info['connected_clients']}" }
|
70
|
+
false
|
71
|
+
end
|
52
72
|
end
|
53
73
|
|
54
74
|
end
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web.rb
CHANGED
@@ -11,6 +11,9 @@ module Sidekiq
|
|
11
11
|
class Web < Sinatra::Base
|
12
12
|
include Sidekiq::Paginator
|
13
13
|
|
14
|
+
enable :sessions
|
15
|
+
use Rack::Protection, :use => :authenticity_token unless ENV['RACK_ENV'] == 'test'
|
16
|
+
|
14
17
|
set :root, File.expand_path(File.dirname(__FILE__) + "/../../web")
|
15
18
|
set :public_folder, proc { "#{root}/assets" }
|
16
19
|
set :views, proc { "#{root}/views" }
|
@@ -98,7 +101,7 @@ module Sidekiq
|
|
98
101
|
end
|
99
102
|
|
100
103
|
post '/morgue' do
|
101
|
-
|
104
|
+
redirect request.path unless params['key']
|
102
105
|
|
103
106
|
params['key'].each do |key|
|
104
107
|
job = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
|
@@ -259,3 +262,16 @@ module Sidekiq
|
|
259
262
|
end
|
260
263
|
end
|
261
264
|
end
|
265
|
+
|
266
|
+
if defined?(::ActionDispatch::Request::Session) &&
|
267
|
+
!::ActionDispatch::Request::Session.respond_to?(:each)
|
268
|
+
# mperham/sidekiq#2460
|
269
|
+
# Rack apps can't reuse the Rails session store without
|
270
|
+
# this monkeypatch
|
271
|
+
class ActionDispatch::Request::Session
|
272
|
+
def each(&block)
|
273
|
+
hash = self.to_hash
|
274
|
+
hash.each(&block)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
data/lib/sidekiq/web_helpers.rb
CHANGED
@@ -45,7 +45,7 @@ module Sidekiq
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def display_custom_head
|
48
|
-
return unless @head_html
|
48
|
+
return unless defined?(@head_html)
|
49
49
|
@head_html.map { |block| capture(&block) }.join
|
50
50
|
end
|
51
51
|
|
@@ -160,7 +160,7 @@ module Sidekiq
|
|
160
160
|
options = options.stringify_keys
|
161
161
|
params.merge(options).map do |key, value|
|
162
162
|
SAFE_QPARAMS.include?(key) ? "#{key}=#{value}" : next
|
163
|
-
end.join("&")
|
163
|
+
end.compact.join("&")
|
164
164
|
end
|
165
165
|
|
166
166
|
def truncate(text, truncate_after_chars = 2000)
|
@@ -169,11 +169,26 @@ module Sidekiq
|
|
169
169
|
|
170
170
|
def display_args(args, truncate_after_chars = 2000)
|
171
171
|
args.map do |arg|
|
172
|
-
|
173
|
-
h(truncate(a))
|
172
|
+
h(truncate(to_display(arg)))
|
174
173
|
end.join(", ")
|
175
174
|
end
|
176
175
|
|
176
|
+
def csrf_tag
|
177
|
+
"<input type='hidden' name='authenticity_token' value='#{session[:csrf]}'/>"
|
178
|
+
end
|
179
|
+
|
180
|
+
def to_display(arg)
|
181
|
+
begin
|
182
|
+
arg.inspect
|
183
|
+
rescue
|
184
|
+
begin
|
185
|
+
arg.to_s
|
186
|
+
rescue => ex
|
187
|
+
"Cannot display argument: [#{ex.class.name}] #{ex.message}"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
177
192
|
RETRY_JOB_KEYS = Set.new(%w(
|
178
193
|
queue class args retry_count retried_at failed_at
|
179
194
|
jid error_message error_class backtrace
|
@@ -230,5 +245,12 @@ module Sidekiq
|
|
230
245
|
def product_version
|
231
246
|
"Sidekiq v#{Sidekiq::VERSION}"
|
232
247
|
end
|
248
|
+
|
249
|
+
def redis_connection_and_namespace
|
250
|
+
@redis_connection_and_namespace ||= begin
|
251
|
+
namespace_suffix = namespace == nil ? '' : "##{namespace}"
|
252
|
+
"#{redis_connection}#{namespace_suffix}"
|
253
|
+
end
|
254
|
+
end
|
233
255
|
end
|
234
256
|
end
|
data/lib/sidekiq/worker.rb
CHANGED
@@ -24,6 +24,8 @@ module Sidekiq
|
|
24
24
|
attr_accessor :jid
|
25
25
|
|
26
26
|
def self.included(base)
|
27
|
+
raise ArgumentError, "You cannot include Sidekiq::Worker in an ActiveJob: #{base.name}" if base.ancestors.any? {|c| c.name == 'ActiveJob::Base' }
|
28
|
+
|
27
29
|
base.extend(ClassMethods)
|
28
30
|
base.class_attribute :sidekiq_options_hash
|
29
31
|
base.class_attribute :sidekiq_retry_in_block
|
@@ -36,6 +38,18 @@ module Sidekiq
|
|
36
38
|
|
37
39
|
module ClassMethods
|
38
40
|
|
41
|
+
def delay(*args)
|
42
|
+
raise ArgumentError, "Do not call .delay on a Sidekiq::Worker class, call .perform_async"
|
43
|
+
end
|
44
|
+
|
45
|
+
def delay_for(*args)
|
46
|
+
raise ArgumentError, "Do not call .delay_for on a Sidekiq::Worker class, call .perform_in"
|
47
|
+
end
|
48
|
+
|
49
|
+
def delay_until(*args)
|
50
|
+
raise ArgumentError, "Do not call .delay_until on a Sidekiq::Worker class, call .perform_at"
|
51
|
+
end
|
52
|
+
|
39
53
|
def perform_async(*args)
|
40
54
|
client_push('class' => self, 'args' => args)
|
41
55
|
end
|
data/lib/sidekiq.rb
CHANGED
@@ -76,9 +76,19 @@ module Sidekiq
|
|
76
76
|
defined?(Sidekiq::CLI)
|
77
77
|
end
|
78
78
|
|
79
|
-
def self.redis
|
80
|
-
raise ArgumentError, "requires a block" unless
|
81
|
-
redis_pool.with
|
79
|
+
def self.redis
|
80
|
+
raise ArgumentError, "requires a block" unless block_given?
|
81
|
+
redis_pool.with do |conn|
|
82
|
+
retryable = true
|
83
|
+
begin
|
84
|
+
yield conn
|
85
|
+
rescue Redis::CommandError => ex
|
86
|
+
#2550 Failover can cause the server to become a slave, need
|
87
|
+
# to disconnect and reopen the socket to get back to the master.
|
88
|
+
(conn.disconnect!; retryable = false; retry) if retryable && ex.message =~ /READONLY/
|
89
|
+
raise
|
90
|
+
end
|
91
|
+
end
|
82
92
|
end
|
83
93
|
|
84
94
|
def self.redis_pool
|
@@ -100,11 +110,25 @@ module Sidekiq
|
|
100
110
|
end
|
101
111
|
|
102
112
|
def self.server_middleware
|
103
|
-
@server_chain ||=
|
113
|
+
@server_chain ||= default_server_middleware
|
104
114
|
yield @server_chain if block_given?
|
105
115
|
@server_chain
|
106
116
|
end
|
107
117
|
|
118
|
+
def self.default_server_middleware
|
119
|
+
require 'sidekiq/middleware/server/retry_jobs'
|
120
|
+
require 'sidekiq/middleware/server/logging'
|
121
|
+
|
122
|
+
Middleware::Chain.new do |m|
|
123
|
+
m.add Middleware::Server::Logging
|
124
|
+
m.add Middleware::Server::RetryJobs
|
125
|
+
if defined?(::ActiveRecord::Base)
|
126
|
+
require 'sidekiq/middleware/server/active_record'
|
127
|
+
m.add Sidekiq::Middleware::Server::ActiveRecord
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
108
132
|
def self.default_worker_options=(hash)
|
109
133
|
@default_worker_options = default_worker_options.merge(hash.stringify_keys)
|
110
134
|
end
|
@@ -129,16 +153,6 @@ module Sidekiq
|
|
129
153
|
Sidekiq::Logging.logger = log
|
130
154
|
end
|
131
155
|
|
132
|
-
# When set, overrides Sidekiq.options[:average_scheduled_poll_interval] and sets
|
133
|
-
# the average interval that this process will delay before checking for
|
134
|
-
# scheduled jobs or job retries that are ready to run.
|
135
|
-
#
|
136
|
-
# See sidekiq/scheduled.rb for an in-depth explanation of this value
|
137
|
-
def self.poll_interval=(interval)
|
138
|
-
$stderr.puts "DEPRECATION: `config.poll_interval = #{interval}` will be removed in Sidekiq 4. Please update to `config.average_scheduled_poll_interval = #{interval}`."
|
139
|
-
self.options[:poll_interval_average] = interval
|
140
|
-
end
|
141
|
-
|
142
156
|
# How frequently Redis should be checked by a random Sidekiq process for
|
143
157
|
# scheduled and retriable jobs. Each individual process will take turns by
|
144
158
|
# waiting some multiple of this value.
|
@@ -172,6 +186,15 @@ module Sidekiq
|
|
172
186
|
raise ArgumentError, "Invalid event name: #{event}" unless options[:lifecycle_events].key?(event)
|
173
187
|
options[:lifecycle_events][event] << block
|
174
188
|
end
|
189
|
+
|
190
|
+
# We are shutting down Sidekiq but what about workers that
|
191
|
+
# are working on some long job? This error is
|
192
|
+
# raised in workers that have not finished within the hard
|
193
|
+
# timeout limit. This is needed to rollback db transactions,
|
194
|
+
# otherwise Ruby's Thread#kill will commit. See #377.
|
195
|
+
# DO NOT RESCUE THIS ERROR IN YOUR WORKERS
|
196
|
+
class Shutdown < Interrupt; end
|
197
|
+
|
175
198
|
end
|
176
199
|
|
177
200
|
require 'sidekiq/extensions/class_methods'
|
data/sidekiq.gemspec
CHANGED
@@ -4,7 +4,8 @@ require File.expand_path('../lib/sidekiq/version', __FILE__)
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ["Mike Perham"]
|
6
6
|
gem.email = ["mperham@gmail.com"]
|
7
|
-
gem.
|
7
|
+
gem.summary = "Simple, efficient background processing for Ruby"
|
8
|
+
gem.description = "Simple, efficient background processing for Ruby."
|
8
9
|
gem.homepage = "http://sidekiq.org"
|
9
10
|
gem.license = "LGPL-3.0"
|
10
11
|
|
@@ -14,14 +15,13 @@ Gem::Specification.new do |gem|
|
|
14
15
|
gem.name = "sidekiq"
|
15
16
|
gem.require_paths = ["lib"]
|
16
17
|
gem.version = Sidekiq::VERSION
|
17
|
-
gem.add_dependency 'redis', '>= 3.
|
18
|
-
gem.add_dependency '
|
19
|
-
gem.add_dependency '
|
20
|
-
gem.add_dependency '
|
21
|
-
gem.
|
22
|
-
gem.add_development_dependency 'sinatra'
|
23
|
-
gem.add_development_dependency 'minitest', '~> 5.
|
24
|
-
gem.add_development_dependency 'rake'
|
25
|
-
gem.add_development_dependency 'rails', '~> 4.
|
26
|
-
gem.add_development_dependency 'coveralls'
|
18
|
+
gem.add_dependency 'redis', '~> 3.2', '>= 3.2.1'
|
19
|
+
gem.add_dependency 'connection_pool', '~> 2.2', '>= 2.2.0'
|
20
|
+
gem.add_dependency 'json', '~> 1.0'
|
21
|
+
gem.add_dependency 'concurrent-ruby', '~> 1.0'
|
22
|
+
gem.add_development_dependency 'redis-namespace', '~> 1.5', '>= 1.5.2'
|
23
|
+
gem.add_development_dependency 'sinatra', '~> 1.4', '>= 1.4.6'
|
24
|
+
gem.add_development_dependency 'minitest', '~> 5.7', '>= 5.7.0'
|
25
|
+
gem.add_development_dependency 'rake', '~> 10.0'
|
26
|
+
gem.add_development_dependency 'rails', '~> 4', '>= 3.2.0'
|
27
27
|
end
|
data/test/helper.rb
CHANGED
@@ -1,18 +1,32 @@
|
|
1
1
|
$TESTING = true
|
2
|
-
|
3
|
-
|
4
|
-
add_filter "/test/"
|
5
|
-
add_filter "/myapp/"
|
6
|
-
end
|
2
|
+
# disable minitest/parallel threads
|
3
|
+
ENV["N"] = "0"
|
7
4
|
|
8
|
-
|
9
|
-
if ENV.has_key?("SIMPLECOV")
|
5
|
+
if ENV["COVERAGE"]
|
10
6
|
require 'simplecov'
|
11
7
|
SimpleCov.start do
|
12
8
|
add_filter "/test/"
|
13
9
|
add_filter "/myapp/"
|
14
10
|
end
|
15
11
|
end
|
12
|
+
ENV['RACK_ENV'] = ENV['RAILS_ENV'] = 'test'
|
13
|
+
|
14
|
+
trap 'USR1' do
|
15
|
+
threads = Thread.list
|
16
|
+
|
17
|
+
puts
|
18
|
+
puts "=" * 80
|
19
|
+
puts "Received USR1 signal; printing all #{threads.count} thread backtraces."
|
20
|
+
|
21
|
+
threads.each do |thr|
|
22
|
+
description = thr == Thread.main ? "Main thread" : thr.inspect
|
23
|
+
puts
|
24
|
+
puts "#{description} backtrace: "
|
25
|
+
puts thr.backtrace.join("\n")
|
26
|
+
end
|
27
|
+
|
28
|
+
puts "=" * 80
|
29
|
+
end
|
16
30
|
|
17
31
|
begin
|
18
32
|
require 'pry-byebug'
|
@@ -20,10 +34,7 @@ rescue LoadError
|
|
20
34
|
end
|
21
35
|
|
22
36
|
require 'minitest/autorun'
|
23
|
-
require 'minitest/pride'
|
24
37
|
|
25
|
-
require 'celluloid/test'
|
26
|
-
Celluloid.boot
|
27
38
|
require 'sidekiq'
|
28
39
|
require 'sidekiq/util'
|
29
40
|
Sidekiq.logger.level = Logger::ERROR
|
@@ -37,3 +48,27 @@ REDIS = Sidekiq::RedisConnection.create(:url => REDIS_URL, :namespace => 'testy'
|
|
37
48
|
Sidekiq.configure_client do |config|
|
38
49
|
config.redis = { :url => REDIS_URL, :namespace => 'testy' }
|
39
50
|
end
|
51
|
+
|
52
|
+
def capture_logging(lvl=Logger::INFO)
|
53
|
+
old = Sidekiq.logger
|
54
|
+
begin
|
55
|
+
out = StringIO.new
|
56
|
+
logger = Logger.new(out)
|
57
|
+
logger.level = lvl
|
58
|
+
Sidekiq.logger = logger
|
59
|
+
yield
|
60
|
+
out.string
|
61
|
+
ensure
|
62
|
+
Sidekiq.logger = old
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def with_logging(lvl=Logger::DEBUG)
|
67
|
+
old = Sidekiq.logger.level
|
68
|
+
begin
|
69
|
+
Sidekiq.logger.level = lvl
|
70
|
+
yield
|
71
|
+
ensure
|
72
|
+
Sidekiq.logger.level = old
|
73
|
+
end
|
74
|
+
end
|
data/test/test_actors.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
require 'sidekiq/cli'
|
3
|
+
require 'sidekiq/fetch'
|
4
|
+
require 'sidekiq/scheduled'
|
5
|
+
require 'sidekiq/processor'
|
6
|
+
|
7
|
+
class TestActors < Sidekiq::Test
|
8
|
+
class JoeWorker
|
9
|
+
include Sidekiq::Worker
|
10
|
+
def perform(slp)
|
11
|
+
raise "boom" if slp == "boom"
|
12
|
+
sleep(slp) if slp > 0
|
13
|
+
$count += 1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'threads' do
|
18
|
+
before do
|
19
|
+
Sidekiq.redis {|c| c.flushdb}
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'scheduler' do
|
23
|
+
it 'can start and stop' do
|
24
|
+
f = Sidekiq::Scheduled::Poller.new
|
25
|
+
f.start
|
26
|
+
f.terminate
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'can schedule' do
|
30
|
+
ss = Sidekiq::ScheduledSet.new
|
31
|
+
q = Sidekiq::Queue.new
|
32
|
+
|
33
|
+
JoeWorker.perform_in(0.01, 0)
|
34
|
+
|
35
|
+
assert_equal 0, q.size
|
36
|
+
assert_equal 1, ss.size
|
37
|
+
|
38
|
+
sleep 0.015
|
39
|
+
s = Sidekiq::Scheduled::Poller.new
|
40
|
+
s.enqueue
|
41
|
+
assert_equal 1, q.size
|
42
|
+
assert_equal 0, ss.size
|
43
|
+
s.terminate
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'processor' do
|
48
|
+
before do
|
49
|
+
$count = 0
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'can start and stop' do
|
53
|
+
f = Sidekiq::Processor.new(Mgr.new)
|
54
|
+
f.terminate
|
55
|
+
end
|
56
|
+
|
57
|
+
class Mgr
|
58
|
+
attr_reader :latest_error
|
59
|
+
attr_reader :mutex
|
60
|
+
attr_reader :cond
|
61
|
+
def initialize
|
62
|
+
@mutex = ::Mutex.new
|
63
|
+
@cond = ::ConditionVariable.new
|
64
|
+
end
|
65
|
+
def processor_died(inst, err)
|
66
|
+
@latest_error = err
|
67
|
+
@mutex.synchronize do
|
68
|
+
@cond.signal
|
69
|
+
end
|
70
|
+
end
|
71
|
+
def processor_stopped(inst)
|
72
|
+
@mutex.synchronize do
|
73
|
+
@cond.signal
|
74
|
+
end
|
75
|
+
end
|
76
|
+
def options
|
77
|
+
{ :concurrency => 3, :queues => ['default'] }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'can process' do
|
82
|
+
mgr = Mgr.new
|
83
|
+
|
84
|
+
p = Sidekiq::Processor.new(mgr)
|
85
|
+
JoeWorker.perform_async(0)
|
86
|
+
|
87
|
+
a = $count
|
88
|
+
p.process_one
|
89
|
+
b = $count
|
90
|
+
assert_equal a + 1, b
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'deals with errors' do
|
94
|
+
mgr = Mgr.new
|
95
|
+
|
96
|
+
p = Sidekiq::Processor.new(mgr)
|
97
|
+
JoeWorker.perform_async("boom")
|
98
|
+
q = Sidekiq::Queue.new
|
99
|
+
assert_equal 1, q.size
|
100
|
+
|
101
|
+
a = $count
|
102
|
+
mgr.mutex.synchronize do
|
103
|
+
p.start
|
104
|
+
mgr.cond.wait(mgr.mutex)
|
105
|
+
end
|
106
|
+
b = $count
|
107
|
+
assert_equal a, b
|
108
|
+
|
109
|
+
sleep 0.001
|
110
|
+
assert_equal false, p.thread.status
|
111
|
+
p.terminate(true)
|
112
|
+
refute_nil mgr.latest_error
|
113
|
+
assert_equal RuntimeError, mgr.latest_error.class
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'gracefully kills' do
|
117
|
+
mgr = Mgr.new
|
118
|
+
|
119
|
+
p = Sidekiq::Processor.new(mgr)
|
120
|
+
JoeWorker.perform_async(1)
|
121
|
+
q = Sidekiq::Queue.new
|
122
|
+
assert_equal 1, q.size
|
123
|
+
|
124
|
+
a = $count
|
125
|
+
p.start
|
126
|
+
sleep(0.02)
|
127
|
+
p.terminate
|
128
|
+
p.kill(true)
|
129
|
+
|
130
|
+
b = $count
|
131
|
+
assert_equal a, b
|
132
|
+
assert_equal false, p.thread.status
|
133
|
+
refute mgr.latest_error, mgr.latest_error.to_s
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|