sidekiq 3.4.1 → 4.0.2
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 +3 -2
- data/4.0-Upgrade.md +50 -0
- data/COMM-LICENSE +55 -45
- data/Changes.md +85 -1
- data/Ent-Changes.md +79 -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 +60 -2
- data/README.md +20 -16
- data/bin/sidekiq +4 -0
- data/bin/sidekiqctl +8 -2
- data/bin/sidekiqload +167 -0
- data/lib/generators/sidekiq/templates/worker_spec.rb.erb +2 -2
- data/lib/generators/sidekiq/templates/worker_test.rb.erb +5 -5
- data/lib/sidekiq/api.rb +43 -33
- 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 +80 -180
- data/lib/sidekiq/middleware/server/logging.rb +13 -8
- data/lib/sidekiq/middleware/server/retry_jobs.rb +6 -6
- 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 +139 -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 +33 -5
- data/lib/sidekiq/worker.rb +16 -0
- data/lib/sidekiq.rb +37 -14
- data/sidekiq.gemspec +10 -11
- data/test/helper.rb +45 -10
- data/test/test_actors.rb +137 -0
- data/test/test_api.rb +417 -384
- 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 +83 -8
- data/test/test_testing_inline.rb +3 -3
- data/test/test_util.rb +16 -0
- data/test/test_web.rb +28 -9
- 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 +2 -0
- data/web/locales/fr.yml +2 -2
- data/web/locales/ja.yml +10 -1
- 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 +5 -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 +75 -55
- data/lib/sidekiq/actor.rb +0 -39
- data/test/test_worker_generator.rb +0 -17
data/lib/sidekiq/testing.rb
CHANGED
@@ -48,6 +48,12 @@ module Sidekiq
|
|
48
48
|
def inline?
|
49
49
|
self.__test_mode == :inline
|
50
50
|
end
|
51
|
+
|
52
|
+
def server_middleware
|
53
|
+
@server_chain ||= Middleware::Chain.new
|
54
|
+
yield @server_chain if block_given?
|
55
|
+
@server_chain
|
56
|
+
end
|
51
57
|
end
|
52
58
|
end
|
53
59
|
|
@@ -62,15 +68,15 @@ module Sidekiq
|
|
62
68
|
def raw_push(payloads)
|
63
69
|
if Sidekiq::Testing.fake?
|
64
70
|
payloads.each do |job|
|
65
|
-
job['class']
|
71
|
+
Queues.push(job['queue'], job['class'], Sidekiq.load_json(Sidekiq.dump_json(job)))
|
66
72
|
end
|
67
73
|
true
|
68
74
|
elsif Sidekiq::Testing.inline?
|
69
75
|
payloads.each do |job|
|
70
|
-
job['jid'] ||= SecureRandom.hex(12)
|
71
76
|
klass = job['class'].constantize
|
72
|
-
|
73
|
-
|
77
|
+
job['id'] ||= SecureRandom.hex(12)
|
78
|
+
job_hash = Sidekiq.load_json(Sidekiq.dump_json(job))
|
79
|
+
klass.process_job(job_hash)
|
74
80
|
end
|
75
81
|
true
|
76
82
|
else
|
@@ -79,6 +85,107 @@ module Sidekiq
|
|
79
85
|
end
|
80
86
|
end
|
81
87
|
|
88
|
+
module Queues
|
89
|
+
##
|
90
|
+
# The Queues class is only for testing the fake queue implementation.
|
91
|
+
# There are 2 data structures involved in tandem. This is due to the
|
92
|
+
# Rspec syntax of change(QueueWorker.jobs, :size). It keeps a reference
|
93
|
+
# to the array. Because the array was dervied from a filter of the total
|
94
|
+
# jobs enqueued, it appeared as though the array didn't change.
|
95
|
+
#
|
96
|
+
# To solve this, we'll keep 2 hashes containing the jobs. One with keys based
|
97
|
+
# on the queue, and another with keys of the worker names, so the array for
|
98
|
+
# QueueWorker.jobs is a straight reference to a real array.
|
99
|
+
#
|
100
|
+
# Queue-based hash:
|
101
|
+
#
|
102
|
+
# {
|
103
|
+
# "default"=>[
|
104
|
+
# {
|
105
|
+
# "class"=>"TestTesting::QueueWorker",
|
106
|
+
# "args"=>[1, 2],
|
107
|
+
# "retry"=>true,
|
108
|
+
# "queue"=>"default",
|
109
|
+
# "jid"=>"abc5b065c5c4b27fc1102833",
|
110
|
+
# "created_at"=>1447445554.419934
|
111
|
+
# }
|
112
|
+
# ]
|
113
|
+
# }
|
114
|
+
#
|
115
|
+
# Worker-based hash:
|
116
|
+
#
|
117
|
+
# {
|
118
|
+
# "TestTesting::QueueWorker"=>[
|
119
|
+
# {
|
120
|
+
# "class"=>"TestTesting::QueueWorker",
|
121
|
+
# "args"=>[1, 2],
|
122
|
+
# "retry"=>true,
|
123
|
+
# "queue"=>"default",
|
124
|
+
# "jid"=>"abc5b065c5c4b27fc1102833",
|
125
|
+
# "created_at"=>1447445554.419934
|
126
|
+
# }
|
127
|
+
# ]
|
128
|
+
# }
|
129
|
+
#
|
130
|
+
# Example:
|
131
|
+
#
|
132
|
+
# require 'sidekiq/testing'
|
133
|
+
#
|
134
|
+
# assert_equal 0, Sidekiq::Queues["default"].size
|
135
|
+
# HardWorker.perform_async(:something)
|
136
|
+
# assert_equal 1, Sidekiq::Queues["default"].size
|
137
|
+
# assert_equal :something, Sidekiq::Queues["default"].first['args'][0]
|
138
|
+
#
|
139
|
+
# You can also clear all workers' jobs:
|
140
|
+
#
|
141
|
+
# assert_equal 0, Sidekiq::Queues["default"].size
|
142
|
+
# HardWorker.perform_async(:something)
|
143
|
+
# Sidekiq::Queues.clear_all
|
144
|
+
# assert_equal 0, Sidekiq::Queues["default"].size
|
145
|
+
#
|
146
|
+
# This can be useful to make sure jobs don't linger between tests:
|
147
|
+
#
|
148
|
+
# RSpec.configure do |config|
|
149
|
+
# config.before(:each) do
|
150
|
+
# Sidekiq::Queues.clear_all
|
151
|
+
# end
|
152
|
+
# end
|
153
|
+
#
|
154
|
+
class << self
|
155
|
+
def [](queue)
|
156
|
+
jobs_by_queue[queue]
|
157
|
+
end
|
158
|
+
|
159
|
+
def push(queue, klass, job)
|
160
|
+
jobs_by_queue[queue] << job
|
161
|
+
jobs_by_worker[klass] << job
|
162
|
+
end
|
163
|
+
|
164
|
+
def jobs_by_queue
|
165
|
+
@jobs_by_queue ||= Hash.new { |hash, key| hash[key] = [] }
|
166
|
+
end
|
167
|
+
|
168
|
+
def jobs_by_worker
|
169
|
+
@jobs_by_worker ||= Hash.new { |hash, key| hash[key] = [] }
|
170
|
+
end
|
171
|
+
|
172
|
+
def delete_for(jid, queue, klass)
|
173
|
+
jobs_by_queue[queue].delete_if { |job| job["jid"] == jid }
|
174
|
+
jobs_by_worker[klass].delete_if { |job| job["jid"] == jid }
|
175
|
+
end
|
176
|
+
|
177
|
+
def clear_for(queue, klass)
|
178
|
+
jobs_by_queue[queue].clear
|
179
|
+
jobs_by_worker[klass].clear
|
180
|
+
end
|
181
|
+
|
182
|
+
def clear_all
|
183
|
+
jobs_by_queue.clear
|
184
|
+
jobs_by_worker.clear
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
82
189
|
module Worker
|
83
190
|
##
|
84
191
|
# The Sidekiq testing infrastructure overrides perform_async
|
@@ -137,34 +244,45 @@ module Sidekiq
|
|
137
244
|
#
|
138
245
|
module ClassMethods
|
139
246
|
|
247
|
+
# Queue for this worker
|
248
|
+
def queue
|
249
|
+
self.sidekiq_options["queue"]
|
250
|
+
end
|
251
|
+
|
140
252
|
# Jobs queued for this worker
|
141
253
|
def jobs
|
142
|
-
|
254
|
+
Queues.jobs_by_worker[self.to_s]
|
143
255
|
end
|
144
256
|
|
145
257
|
# Clear all jobs for this worker
|
146
258
|
def clear
|
147
|
-
|
259
|
+
Queues.clear_for(queue, self.to_s)
|
148
260
|
end
|
149
261
|
|
150
262
|
# Drain and run all jobs for this worker
|
151
263
|
def drain
|
152
|
-
while
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
execute_job(worker, job['args'])
|
264
|
+
while jobs.any?
|
265
|
+
next_job = jobs.first
|
266
|
+
Queues.delete_for(next_job["jid"], queue, self.to_s)
|
267
|
+
process_job(next_job)
|
157
268
|
end
|
158
269
|
end
|
159
270
|
|
160
271
|
# Pop out a single job and perform it
|
161
272
|
def perform_one
|
162
273
|
raise(EmptyQueueError, "perform_one called with empty job queue") if jobs.empty?
|
163
|
-
|
274
|
+
next_job = jobs.first
|
275
|
+
Queues.delete_for(next_job["jid"], queue, self.to_s)
|
276
|
+
process_job(next_job)
|
277
|
+
end
|
278
|
+
|
279
|
+
def process_job(job)
|
164
280
|
worker = new
|
165
281
|
worker.jid = job['jid']
|
166
282
|
worker.bid = job['bid'] if worker.respond_to?(:bid=)
|
167
|
-
|
283
|
+
Sidekiq::Testing.server_middleware.invoke(worker, job, job['queue']) do
|
284
|
+
execute_job(worker, job['args'])
|
285
|
+
end
|
168
286
|
end
|
169
287
|
|
170
288
|
def execute_job(worker, args)
|
@@ -174,18 +292,22 @@ module Sidekiq
|
|
174
292
|
|
175
293
|
class << self
|
176
294
|
def jobs # :nodoc:
|
177
|
-
|
295
|
+
Queues.jobs_by_queue.values.flatten
|
178
296
|
end
|
179
297
|
|
180
298
|
# Clear all queued jobs across all workers
|
181
299
|
def clear_all
|
182
|
-
|
300
|
+
Queues.clear_all
|
183
301
|
end
|
184
302
|
|
185
303
|
# Drain all queued jobs across all workers
|
186
304
|
def drain_all
|
187
|
-
|
188
|
-
jobs.
|
305
|
+
while jobs.any?
|
306
|
+
worker_classes = jobs.map { |job| job["class"] }.uniq
|
307
|
+
|
308
|
+
worker_classes.each do |worker_class|
|
309
|
+
worker_class.constantize.drain
|
310
|
+
end
|
189
311
|
end
|
190
312
|
end
|
191
313
|
end
|
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
@@ -17,8 +17,13 @@ module Sidekiq
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
def clear_caches
|
21
|
+
@@strings = nil
|
22
|
+
@@locale_files = nil
|
23
|
+
end
|
24
|
+
|
20
25
|
def locale_files
|
21
|
-
@@locale_files
|
26
|
+
@@locale_files ||= settings.locales.flat_map do |path|
|
22
27
|
Dir["#{path}/*.yml"]
|
23
28
|
end
|
24
29
|
end
|
@@ -45,7 +50,7 @@ module Sidekiq
|
|
45
50
|
end
|
46
51
|
|
47
52
|
def display_custom_head
|
48
|
-
return unless @head_html
|
53
|
+
return unless defined?(@head_html)
|
49
54
|
@head_html.map { |block| capture(&block) }.join
|
50
55
|
end
|
51
56
|
|
@@ -160,7 +165,7 @@ module Sidekiq
|
|
160
165
|
options = options.stringify_keys
|
161
166
|
params.merge(options).map do |key, value|
|
162
167
|
SAFE_QPARAMS.include?(key) ? "#{key}=#{value}" : next
|
163
|
-
end.join("&")
|
168
|
+
end.compact.join("&")
|
164
169
|
end
|
165
170
|
|
166
171
|
def truncate(text, truncate_after_chars = 2000)
|
@@ -169,15 +174,31 @@ module Sidekiq
|
|
169
174
|
|
170
175
|
def display_args(args, truncate_after_chars = 2000)
|
171
176
|
args.map do |arg|
|
172
|
-
|
173
|
-
h(truncate(a))
|
177
|
+
h(truncate(to_display(arg)))
|
174
178
|
end.join(", ")
|
175
179
|
end
|
176
180
|
|
181
|
+
def csrf_tag
|
182
|
+
"<input type='hidden' name='authenticity_token' value='#{session[:csrf]}'/>"
|
183
|
+
end
|
184
|
+
|
185
|
+
def to_display(arg)
|
186
|
+
begin
|
187
|
+
arg.inspect
|
188
|
+
rescue
|
189
|
+
begin
|
190
|
+
arg.to_s
|
191
|
+
rescue => ex
|
192
|
+
"Cannot display argument: [#{ex.class.name}] #{ex.message}"
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
177
197
|
RETRY_JOB_KEYS = Set.new(%w(
|
178
198
|
queue class args retry_count retried_at failed_at
|
179
199
|
jid error_message error_class backtrace
|
180
200
|
error_backtrace enqueued_at retry wrapped
|
201
|
+
created_at
|
181
202
|
))
|
182
203
|
|
183
204
|
def retry_extra_items(retry_job)
|
@@ -230,5 +251,12 @@ module Sidekiq
|
|
230
251
|
def product_version
|
231
252
|
"Sidekiq v#{Sidekiq::VERSION}"
|
232
253
|
end
|
254
|
+
|
255
|
+
def redis_connection_and_namespace
|
256
|
+
@redis_connection_and_namespace ||= begin
|
257
|
+
namespace_suffix = namespace == nil ? '' : "##{namespace}"
|
258
|
+
"#{redis_connection}#{namespace_suffix}"
|
259
|
+
end
|
260
|
+
end
|
233
261
|
end
|
234
262
|
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,10 +38,24 @@ 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
|
42
56
|
|
57
|
+
# +interval+ must be a timestamp, numeric or something that acts
|
58
|
+
# numeric (like an activesupport time interval).
|
43
59
|
def perform_in(interval, *args)
|
44
60
|
int = interval.to_f
|
45
61
|
now = Time.now
|
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,12 @@ 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.
|
21
|
-
gem.
|
22
|
-
gem.add_development_dependency '
|
23
|
-
gem.add_development_dependency '
|
24
|
-
gem.add_development_dependency '
|
25
|
-
gem.add_development_dependency 'rails', '~> 4.1.1'
|
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 'concurrent-ruby', '~> 1.0'
|
21
|
+
gem.add_development_dependency 'redis-namespace', '~> 1.5', '>= 1.5.2'
|
22
|
+
gem.add_development_dependency 'sinatra', '~> 1.4', '>= 1.4.6'
|
23
|
+
gem.add_development_dependency 'minitest', '~> 5.7', '>= 5.7.0'
|
24
|
+
gem.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
gem.add_development_dependency 'rails', '~> 4', '>= 3.2.0'
|
27
26
|
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
|