sidekiq 4.2.4 → 5.2.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/.github/issue_template.md +8 -1
- data/.gitignore +1 -0
- data/.travis.yml +5 -3
- data/5.0-Upgrade.md +56 -0
- data/COMM-LICENSE +1 -1
- data/Changes.md +151 -0
- data/Ent-Changes.md +77 -2
- data/Gemfile +10 -25
- data/LICENSE +1 -1
- data/Pro-4.0-Upgrade.md +35 -0
- data/Pro-Changes.md +156 -2
- data/README.md +9 -6
- data/Rakefile +1 -2
- data/bin/sidekiqctl +1 -1
- data/bin/sidekiqload +15 -33
- data/lib/generators/sidekiq/templates/worker_spec.rb.erb +1 -1
- data/lib/generators/sidekiq/templates/worker_test.rb.erb +1 -1
- data/lib/sidekiq/api.rb +157 -67
- data/lib/sidekiq/cli.rb +71 -26
- data/lib/sidekiq/client.rb +25 -18
- data/lib/sidekiq/core_ext.rb +1 -106
- data/lib/sidekiq/delay.rb +42 -0
- data/lib/sidekiq/exception_handler.rb +2 -4
- data/lib/sidekiq/extensions/generic_proxy.rb +7 -1
- data/lib/sidekiq/fetch.rb +1 -1
- data/lib/sidekiq/job_logger.rb +25 -0
- data/lib/sidekiq/job_retry.rb +241 -0
- data/lib/sidekiq/launcher.rb +45 -37
- data/lib/sidekiq/logging.rb +18 -2
- data/lib/sidekiq/manager.rb +3 -4
- data/lib/sidekiq/middleware/server/active_record.rb +10 -0
- data/lib/sidekiq/processor.rb +91 -34
- data/lib/sidekiq/rails.rb +15 -51
- data/lib/sidekiq/redis_connection.rb +31 -5
- data/lib/sidekiq/scheduled.rb +35 -8
- data/lib/sidekiq/testing.rb +24 -7
- data/lib/sidekiq/util.rb +6 -2
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/action.rb +2 -6
- data/lib/sidekiq/web/application.rb +28 -21
- data/lib/sidekiq/web/helpers.rb +67 -23
- data/lib/sidekiq/web/router.rb +14 -10
- data/lib/sidekiq/web.rb +4 -4
- data/lib/sidekiq/worker.rb +97 -14
- data/lib/sidekiq.rb +23 -24
- data/sidekiq.gemspec +7 -10
- data/web/assets/javascripts/application.js +0 -0
- data/web/assets/javascripts/dashboard.js +18 -13
- data/web/assets/stylesheets/application-rtl.css +246 -0
- data/web/assets/stylesheets/application.css +336 -4
- data/web/assets/stylesheets/bootstrap-rtl.min.css +9 -0
- data/web/assets/stylesheets/bootstrap.css +2 -2
- data/web/locales/ar.yml +80 -0
- data/web/locales/en.yml +1 -0
- data/web/locales/es.yml +4 -3
- data/web/locales/fa.yml +80 -0
- data/web/locales/he.yml +79 -0
- data/web/locales/ja.yml +5 -3
- data/web/locales/ur.yml +80 -0
- data/web/views/_footer.erb +5 -2
- data/web/views/_job_info.erb +1 -1
- data/web/views/_nav.erb +1 -1
- data/web/views/_paging.erb +1 -1
- data/web/views/busy.erb +9 -5
- data/web/views/dashboard.erb +3 -3
- data/web/views/layout.erb +11 -2
- data/web/views/morgue.erb +14 -10
- data/web/views/queue.erb +10 -10
- data/web/views/queues.erb +4 -2
- data/web/views/retries.erb +13 -11
- data/web/views/retry.erb +1 -1
- data/web/views/scheduled.erb +2 -2
- metadata +26 -160
- data/lib/sidekiq/middleware/server/logging.rb +0 -40
- data/lib/sidekiq/middleware/server/retry_jobs.rb +0 -205
- data/test/config.yml +0 -9
- data/test/env_based_config.yml +0 -11
- data/test/fake_env.rb +0 -1
- data/test/fixtures/en.yml +0 -2
- data/test/helper.rb +0 -75
- data/test/test_actors.rb +0 -138
- data/test/test_api.rb +0 -528
- data/test/test_cli.rb +0 -418
- data/test/test_client.rb +0 -266
- data/test/test_exception_handler.rb +0 -56
- data/test/test_extensions.rb +0 -127
- data/test/test_fetch.rb +0 -50
- data/test/test_launcher.rb +0 -95
- data/test/test_logging.rb +0 -35
- data/test/test_manager.rb +0 -50
- data/test/test_middleware.rb +0 -158
- data/test/test_processor.rb +0 -235
- data/test/test_rails.rb +0 -22
- data/test/test_redis_connection.rb +0 -132
- data/test/test_retry.rb +0 -326
- data/test/test_retry_exhausted.rb +0 -149
- data/test/test_scheduled.rb +0 -115
- data/test/test_scheduling.rb +0 -58
- data/test/test_sidekiq.rb +0 -107
- data/test/test_testing.rb +0 -143
- data/test/test_testing_fake.rb +0 -357
- data/test/test_testing_inline.rb +0 -94
- data/test/test_util.rb +0 -13
- data/test/test_web.rb +0 -726
- data/test/test_web_helpers.rb +0 -54
data/test/test_retry.rb
DELETED
@@ -1,326 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
# encoding: utf-8
|
3
|
-
require_relative 'helper'
|
4
|
-
require 'sidekiq/scheduled'
|
5
|
-
require 'sidekiq/middleware/server/retry_jobs'
|
6
|
-
|
7
|
-
class TestRetry < Sidekiq::Test
|
8
|
-
describe 'middleware' do
|
9
|
-
class SomeWorker
|
10
|
-
include Sidekiq::Worker
|
11
|
-
end
|
12
|
-
|
13
|
-
before do
|
14
|
-
Sidekiq.redis {|c| c.flushdb }
|
15
|
-
end
|
16
|
-
|
17
|
-
def worker
|
18
|
-
@worker ||= SomeWorker.new
|
19
|
-
end
|
20
|
-
|
21
|
-
def handler(options={})
|
22
|
-
@handler ||= Sidekiq::Middleware::Server::RetryJobs.new(options)
|
23
|
-
end
|
24
|
-
|
25
|
-
def job(options={})
|
26
|
-
@job ||= { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }.merge(options)
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'allows disabling retry' do
|
30
|
-
assert_raises RuntimeError do
|
31
|
-
handler.call(worker, job('retry' => false), 'default') do
|
32
|
-
raise "kerblammo!"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
assert_equal 0, Sidekiq::RetrySet.new.size
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'allows a numeric retry' do
|
39
|
-
assert_raises RuntimeError do
|
40
|
-
handler.call(worker, job('retry' => 2), 'default') do
|
41
|
-
raise "kerblammo!"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
assert_equal 1, Sidekiq::RetrySet.new.size
|
45
|
-
assert_equal 0, Sidekiq::DeadSet.new.size
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'allows 0 retry => no retry and dead queue' do
|
49
|
-
assert_raises RuntimeError do
|
50
|
-
handler.call(worker, job('retry' => 0), 'default') do
|
51
|
-
raise "kerblammo!"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
assert_equal 0, Sidekiq::RetrySet.new.size
|
55
|
-
assert_equal 1, Sidekiq::DeadSet.new.size
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'handles zany characters in error message, #1705' do
|
59
|
-
skip 'skipped! test requires ruby 2.1+' if RUBY_VERSION <= '2.1.0'
|
60
|
-
|
61
|
-
assert_raises RuntimeError do
|
62
|
-
handler.call(worker, job, 'default') do
|
63
|
-
raise "kerblammo! #{195.chr}"
|
64
|
-
end
|
65
|
-
end
|
66
|
-
assert_equal "kerblammo! �", job["error_message"]
|
67
|
-
end
|
68
|
-
|
69
|
-
|
70
|
-
it 'allows a max_retries option in initializer' do
|
71
|
-
max_retries = 7
|
72
|
-
1.upto(max_retries + 1) do
|
73
|
-
assert_raises RuntimeError do
|
74
|
-
handler(:max_retries => max_retries).call(worker, job, 'default') do
|
75
|
-
raise "kerblammo!"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
assert_equal max_retries, Sidekiq::RetrySet.new.size
|
81
|
-
assert_equal 1, Sidekiq::DeadSet.new.size
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'saves backtraces' do
|
85
|
-
c = nil
|
86
|
-
assert_raises RuntimeError do
|
87
|
-
handler.call(worker, job('backtrace' => true), 'default') do
|
88
|
-
c = caller(0); raise "kerblammo!"
|
89
|
-
end
|
90
|
-
end
|
91
|
-
assert job["error_backtrace"]
|
92
|
-
assert_equal c[0], job["error_backtrace"][0]
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'saves partial backtraces' do
|
96
|
-
c = nil
|
97
|
-
assert_raises RuntimeError do
|
98
|
-
handler.call(worker, job('backtrace' => 3), 'default') do
|
99
|
-
c = caller(0)[0...3]; raise "kerblammo!"
|
100
|
-
end
|
101
|
-
end
|
102
|
-
assert job["error_backtrace"]
|
103
|
-
assert_equal c, job["error_backtrace"]
|
104
|
-
assert_equal 3, c.size
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'handles a new failed message' do
|
108
|
-
assert_raises RuntimeError do
|
109
|
-
handler.call(worker, job, 'default') do
|
110
|
-
raise "kerblammo!"
|
111
|
-
end
|
112
|
-
end
|
113
|
-
assert_equal 'default', job["queue"]
|
114
|
-
assert_equal 'kerblammo!', job["error_message"]
|
115
|
-
assert_equal 'RuntimeError', job["error_class"]
|
116
|
-
assert_equal 0, job["retry_count"]
|
117
|
-
refute job["error_backtrace"]
|
118
|
-
assert job["failed_at"]
|
119
|
-
end
|
120
|
-
|
121
|
-
it 'shuts down without retrying work-in-progress, which will resume' do
|
122
|
-
rs = Sidekiq::RetrySet.new
|
123
|
-
assert_equal 0, rs.size
|
124
|
-
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
|
125
|
-
assert_raises Sidekiq::Shutdown do
|
126
|
-
handler.call(worker, msg, 'default') do
|
127
|
-
raise Sidekiq::Shutdown
|
128
|
-
end
|
129
|
-
end
|
130
|
-
assert_equal 0, rs.size
|
131
|
-
end
|
132
|
-
|
133
|
-
it 'shuts down cleanly when shutdown causes exception' do
|
134
|
-
skip('Not supported in Ruby < 2.1.0') if RUBY_VERSION < '2.1.0'
|
135
|
-
|
136
|
-
rs = Sidekiq::RetrySet.new
|
137
|
-
assert_equal 0, rs.size
|
138
|
-
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
|
139
|
-
assert_raises Sidekiq::Shutdown do
|
140
|
-
handler.call(worker, msg, 'default') do
|
141
|
-
begin
|
142
|
-
raise Sidekiq::Shutdown
|
143
|
-
rescue Interrupt
|
144
|
-
raise "kerblammo!"
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
assert_equal 0, rs.size
|
149
|
-
end
|
150
|
-
|
151
|
-
it 'shuts down cleanly when shutdown causes chained exceptions' do
|
152
|
-
skip('Not supported in Ruby < 2.1.0') if RUBY_VERSION < '2.1.0'
|
153
|
-
|
154
|
-
rs = Sidekiq::RetrySet.new
|
155
|
-
assert_equal 0, rs.size
|
156
|
-
assert_raises Sidekiq::Shutdown do
|
157
|
-
handler.call(worker, job, 'default') do
|
158
|
-
begin
|
159
|
-
raise Sidekiq::Shutdown
|
160
|
-
rescue Interrupt
|
161
|
-
begin
|
162
|
-
raise "kerblammo!"
|
163
|
-
rescue
|
164
|
-
raise "kablooie!"
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
assert_equal 0, rs.size
|
170
|
-
end
|
171
|
-
|
172
|
-
it 'allows a retry queue' do
|
173
|
-
assert_raises RuntimeError do
|
174
|
-
handler.call(worker, job("retry_queue" => 'retryx'), 'default') do
|
175
|
-
raise "kerblammo!"
|
176
|
-
end
|
177
|
-
end
|
178
|
-
assert_equal 'retryx', job["queue"]
|
179
|
-
assert_equal 'kerblammo!', job["error_message"]
|
180
|
-
assert_equal 'RuntimeError', job["error_class"]
|
181
|
-
assert_equal 0, job["retry_count"]
|
182
|
-
refute job["error_backtrace"]
|
183
|
-
assert job["failed_at"]
|
184
|
-
end
|
185
|
-
|
186
|
-
it 'handles a recurring failed message' do
|
187
|
-
now = Time.now.to_f
|
188
|
-
msg = {"queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>10}
|
189
|
-
assert_raises RuntimeError do
|
190
|
-
handler.call(worker, job(msg), 'default') do
|
191
|
-
raise "kerblammo!"
|
192
|
-
end
|
193
|
-
end
|
194
|
-
assert_equal 'default', job["queue"]
|
195
|
-
assert_equal 'kerblammo!', job["error_message"]
|
196
|
-
assert_equal 'RuntimeError', job["error_class"]
|
197
|
-
assert_equal 11, job["retry_count"]
|
198
|
-
assert job["failed_at"]
|
199
|
-
end
|
200
|
-
|
201
|
-
it 'throws away old messages after too many retries (using the default)' do
|
202
|
-
q = Sidekiq::Queue.new
|
203
|
-
rs = Sidekiq::RetrySet.new
|
204
|
-
ds = Sidekiq::DeadSet.new
|
205
|
-
assert_equal 0, q.size
|
206
|
-
assert_equal 0, rs.size
|
207
|
-
assert_equal 0, ds.size
|
208
|
-
now = Time.now.to_f
|
209
|
-
msg = {"queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>25}
|
210
|
-
assert_raises RuntimeError do
|
211
|
-
handler.call(worker, job(msg), 'default') do
|
212
|
-
raise "kerblammo!"
|
213
|
-
end
|
214
|
-
end
|
215
|
-
assert_equal 0, q.size
|
216
|
-
assert_equal 0, rs.size
|
217
|
-
assert_equal 1, ds.size
|
218
|
-
end
|
219
|
-
|
220
|
-
describe "custom retry delay" do
|
221
|
-
before do
|
222
|
-
@old_logger = Sidekiq.logger
|
223
|
-
@tmp_log_path = '/tmp/sidekiq-retries.log'
|
224
|
-
Sidekiq.logger = Logger.new(@tmp_log_path)
|
225
|
-
end
|
226
|
-
|
227
|
-
after do
|
228
|
-
Sidekiq.logger = @old_logger
|
229
|
-
Sidekiq.options.delete(:logfile)
|
230
|
-
File.unlink @tmp_log_path if File.exist?(@tmp_log_path)
|
231
|
-
end
|
232
|
-
|
233
|
-
class CustomWorkerWithoutException
|
234
|
-
include Sidekiq::Worker
|
235
|
-
|
236
|
-
sidekiq_retry_in do |count|
|
237
|
-
count * 2
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
class CustomWorkerWithException
|
242
|
-
include Sidekiq::Worker
|
243
|
-
|
244
|
-
sidekiq_retry_in do |count, exception|
|
245
|
-
case exception
|
246
|
-
when ArgumentError
|
247
|
-
count * 4
|
248
|
-
else
|
249
|
-
count * 2
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
class ErrorWorker
|
255
|
-
include Sidekiq::Worker
|
256
|
-
|
257
|
-
sidekiq_retry_in do |count|
|
258
|
-
count / 0
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
it "retries with a default delay" do
|
263
|
-
refute_equal 4, handler.__send__(:delay_for, worker, 2, StandardError.new)
|
264
|
-
end
|
265
|
-
|
266
|
-
it "retries with a custom delay and exception 1" do
|
267
|
-
assert_equal 8, handler.__send__(:delay_for, CustomWorkerWithException, 2, ArgumentError.new)
|
268
|
-
end
|
269
|
-
|
270
|
-
it "retries with a custom delay and exception 2" do
|
271
|
-
assert_equal 4, handler.__send__(:delay_for, CustomWorkerWithException, 2, StandardError.new)
|
272
|
-
end
|
273
|
-
|
274
|
-
it "retries with a custom delay without exception" do
|
275
|
-
assert_equal 4, handler.__send__(:delay_for, CustomWorkerWithoutException, 2, StandardError.new)
|
276
|
-
end
|
277
|
-
|
278
|
-
it "falls back to the default retry on exception" do
|
279
|
-
refute_equal 4, handler.__send__(:delay_for, ErrorWorker, 2, StandardError.new)
|
280
|
-
assert_match(/Failure scheduling retry using the defined `sidekiq_retry_in`/,
|
281
|
-
File.read(@tmp_log_path), 'Log entry missing for sidekiq_retry_in')
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
describe 'handles errors withouth cause' do
|
286
|
-
before do
|
287
|
-
@error = nil
|
288
|
-
begin
|
289
|
-
raise ::StandardError, 'Error'
|
290
|
-
rescue ::StandardError => e
|
291
|
-
@error = e
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
it "does not recurse infinitely checking if it's a shutdown" do
|
296
|
-
assert(!Sidekiq::Middleware::Server::RetryJobs.new.send(
|
297
|
-
:exception_caused_by_shutdown?, @error))
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
describe 'handles errors with circular causes' do
|
302
|
-
before do
|
303
|
-
@error = nil
|
304
|
-
begin
|
305
|
-
begin
|
306
|
-
raise ::StandardError, 'Error 1'
|
307
|
-
rescue ::StandardError => e1
|
308
|
-
begin
|
309
|
-
raise ::StandardError, 'Error 2'
|
310
|
-
rescue ::StandardError
|
311
|
-
raise e1
|
312
|
-
end
|
313
|
-
end
|
314
|
-
rescue ::StandardError => e
|
315
|
-
@error = e
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
it "does not recurse infinitely checking if it's a shutdown" do
|
320
|
-
assert(!Sidekiq::Middleware::Server::RetryJobs.new.send(
|
321
|
-
:exception_caused_by_shutdown?, @error))
|
322
|
-
end
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
end
|
@@ -1,149 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require_relative 'helper'
|
3
|
-
require 'sidekiq/middleware/server/retry_jobs'
|
4
|
-
|
5
|
-
class TestRetryExhausted < Sidekiq::Test
|
6
|
-
describe 'sidekiq_retries_exhausted' do
|
7
|
-
class NewWorker
|
8
|
-
include Sidekiq::Worker
|
9
|
-
|
10
|
-
class_attribute :exhausted_called, :exhausted_job, :exhausted_exception
|
11
|
-
|
12
|
-
sidekiq_retries_exhausted do |job, e|
|
13
|
-
self.exhausted_called = true
|
14
|
-
self.exhausted_job = job
|
15
|
-
self.exhausted_exception = e
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class OldWorker
|
20
|
-
include Sidekiq::Worker
|
21
|
-
|
22
|
-
class_attribute :exhausted_called, :exhausted_job, :exhausted_exception
|
23
|
-
|
24
|
-
sidekiq_retries_exhausted do |job|
|
25
|
-
self.exhausted_called = true
|
26
|
-
self.exhausted_job = job
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def cleanup
|
31
|
-
[NewWorker, OldWorker].each do |worker_class|
|
32
|
-
worker_class.exhausted_called = nil
|
33
|
-
worker_class.exhausted_job = nil
|
34
|
-
worker_class.exhausted_exception = nil
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
before do
|
39
|
-
cleanup
|
40
|
-
end
|
41
|
-
|
42
|
-
after do
|
43
|
-
cleanup
|
44
|
-
end
|
45
|
-
|
46
|
-
def new_worker
|
47
|
-
@new_worker ||= NewWorker.new
|
48
|
-
end
|
49
|
-
|
50
|
-
def old_worker
|
51
|
-
@old_worker ||= OldWorker.new
|
52
|
-
end
|
53
|
-
|
54
|
-
def handler(options={})
|
55
|
-
@handler ||= Sidekiq::Middleware::Server::RetryJobs.new(options)
|
56
|
-
end
|
57
|
-
|
58
|
-
def job(options={})
|
59
|
-
@job ||= {'class' => 'Bob', 'args' => [1, 2, 'foo']}.merge(options)
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'does not run exhausted block when job successful on first run' do
|
63
|
-
handler.call(new_worker, job('retry' => 2), 'default') do
|
64
|
-
# successful
|
65
|
-
end
|
66
|
-
|
67
|
-
refute NewWorker.exhausted_called?
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'does not run exhausted block when job successful on last retry' do
|
71
|
-
handler.call(new_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
|
72
|
-
# successful
|
73
|
-
end
|
74
|
-
|
75
|
-
refute NewWorker.exhausted_called?
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'does not run exhausted block when retries not exhausted yet' do
|
79
|
-
assert_raises RuntimeError do
|
80
|
-
handler.call(new_worker, job('retry' => 1), 'default') do
|
81
|
-
raise 'kerblammo!'
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
refute NewWorker.exhausted_called?
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'runs exhausted block when retries exhausted' do
|
89
|
-
assert_raises RuntimeError do
|
90
|
-
handler.call(new_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
|
91
|
-
raise 'kerblammo!'
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
assert NewWorker.exhausted_called?
|
96
|
-
end
|
97
|
-
|
98
|
-
|
99
|
-
it 'passes job and exception to retries exhausted block' do
|
100
|
-
raised_error = assert_raises RuntimeError do
|
101
|
-
handler.call(new_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
|
102
|
-
raise 'kerblammo!'
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
assert new_worker.exhausted_called?
|
107
|
-
assert_equal raised_error.message, new_worker.exhausted_job['error_message']
|
108
|
-
assert_equal raised_error, new_worker.exhausted_exception
|
109
|
-
end
|
110
|
-
|
111
|
-
it 'passes job to retries exhausted block' do
|
112
|
-
raised_error = assert_raises RuntimeError do
|
113
|
-
handler.call(old_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
|
114
|
-
raise 'kerblammo!'
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
assert old_worker.exhausted_called?
|
119
|
-
assert_equal raised_error.message, old_worker.exhausted_job['error_message']
|
120
|
-
assert_equal nil, new_worker.exhausted_exception
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'allows a global default handler' do
|
124
|
-
begin
|
125
|
-
class Foobar
|
126
|
-
include Sidekiq::Worker
|
127
|
-
end
|
128
|
-
|
129
|
-
exhausted_job = nil
|
130
|
-
exhausted_exception = nil
|
131
|
-
Sidekiq.default_retries_exhausted = lambda do |job, ex|
|
132
|
-
exhausted_job = job
|
133
|
-
exhausted_exception = ex
|
134
|
-
end
|
135
|
-
f = Foobar.new
|
136
|
-
raised_error = assert_raises RuntimeError do
|
137
|
-
handler.call(f, job('retry_count' => 0, 'retry' => 1), 'default') do
|
138
|
-
raise 'kerblammo!'
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
assert exhausted_job
|
143
|
-
assert_equal raised_error, exhausted_exception
|
144
|
-
ensure
|
145
|
-
Sidekiq.default_retries_exhausted = nil
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
data/test/test_scheduled.rb
DELETED
@@ -1,115 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require_relative 'helper'
|
3
|
-
require 'sidekiq/scheduled'
|
4
|
-
|
5
|
-
class TestScheduled < Sidekiq::Test
|
6
|
-
class ScheduledWorker
|
7
|
-
include Sidekiq::Worker
|
8
|
-
def perform(x)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
describe 'poller' do
|
13
|
-
before do
|
14
|
-
Sidekiq.redis{|c| c.flushdb}
|
15
|
-
@error_1 = { 'class' => ScheduledWorker.name, 'args' => [0], 'queue' => 'queue_1' }
|
16
|
-
@error_2 = { 'class' => ScheduledWorker.name, 'args' => [1], 'queue' => 'queue_2' }
|
17
|
-
@error_3 = { 'class' => ScheduledWorker.name, 'args' => [2], 'queue' => 'queue_3' }
|
18
|
-
@future_1 = { 'class' => ScheduledWorker.name, 'args' => [3], 'queue' => 'queue_4' }
|
19
|
-
@future_2 = { 'class' => ScheduledWorker.name, 'args' => [4], 'queue' => 'queue_5' }
|
20
|
-
@future_3 = { 'class' => ScheduledWorker.name, 'args' => [5], 'queue' => 'queue_6' }
|
21
|
-
|
22
|
-
@retry = Sidekiq::RetrySet.new
|
23
|
-
@scheduled = Sidekiq::ScheduledSet.new
|
24
|
-
@poller = Sidekiq::Scheduled::Poller.new
|
25
|
-
end
|
26
|
-
|
27
|
-
class Stopper
|
28
|
-
def call(worker_class, job, queue, r)
|
29
|
-
yield if job['args'].first.odd?
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'executes client middleware' do
|
34
|
-
Sidekiq.client_middleware.add Stopper
|
35
|
-
begin
|
36
|
-
@retry.schedule (Time.now - 60).to_f, @error_1
|
37
|
-
@retry.schedule (Time.now - 60).to_f, @error_2
|
38
|
-
@scheduled.schedule (Time.now - 60).to_f, @future_2
|
39
|
-
@scheduled.schedule (Time.now - 60).to_f, @future_3
|
40
|
-
|
41
|
-
@poller.enqueue
|
42
|
-
|
43
|
-
assert_equal 0, Sidekiq::Queue.new("queue_1").size
|
44
|
-
assert_equal 1, Sidekiq::Queue.new("queue_2").size
|
45
|
-
assert_equal 0, Sidekiq::Queue.new("queue_5").size
|
46
|
-
assert_equal 1, Sidekiq::Queue.new("queue_6").size
|
47
|
-
ensure
|
48
|
-
Sidekiq.client_middleware.remove Stopper
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should empty the retry and scheduled queues up to the current time' do
|
53
|
-
created_time = Time.new(2013, 2, 3)
|
54
|
-
enqueued_time = Time.new(2013, 2, 4)
|
55
|
-
|
56
|
-
Time.stub(:now, created_time) do
|
57
|
-
@retry.schedule (enqueued_time - 60).to_f, @error_1.merge!('created_at' => created_time.to_f)
|
58
|
-
@retry.schedule (enqueued_time - 50).to_f, @error_2.merge!('created_at' => created_time.to_f)
|
59
|
-
@retry.schedule (enqueued_time + 60).to_f, @error_3.merge!('created_at' => created_time.to_f)
|
60
|
-
@scheduled.schedule (enqueued_time - 60).to_f, @future_1.merge!('created_at' => created_time.to_f)
|
61
|
-
@scheduled.schedule (enqueued_time - 50).to_f, @future_2.merge!('created_at' => created_time.to_f)
|
62
|
-
@scheduled.schedule (enqueued_time + 60).to_f, @future_3.merge!('created_at' => created_time.to_f)
|
63
|
-
end
|
64
|
-
|
65
|
-
Time.stub(:now, enqueued_time) do
|
66
|
-
@poller.enqueue
|
67
|
-
|
68
|
-
Sidekiq.redis do |conn|
|
69
|
-
%w(queue:queue_1 queue:queue_2 queue:queue_4 queue:queue_5).each do |queue_name|
|
70
|
-
assert_equal 1, conn.llen(queue_name)
|
71
|
-
job = Sidekiq.load_json(conn.lrange(queue_name, 0, -1)[0])
|
72
|
-
assert_equal enqueued_time.to_f, job['enqueued_at']
|
73
|
-
assert_equal created_time.to_f, job['created_at']
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
assert_equal 1, @retry.size
|
78
|
-
assert_equal 1, @scheduled.size
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def with_sidekiq_option(name, value)
|
83
|
-
_original, Sidekiq.options[name] = Sidekiq.options[name], value
|
84
|
-
begin
|
85
|
-
yield
|
86
|
-
ensure
|
87
|
-
Sidekiq.options[name] = _original
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
it 'generates random intervals that target a configured average' do
|
92
|
-
with_sidekiq_option(:poll_interval_average, 10) do
|
93
|
-
i = 500
|
94
|
-
intervals = Array.new(i){ @poller.send(:random_poll_interval) }
|
95
|
-
|
96
|
-
assert intervals.all?{|x| x >= 5}
|
97
|
-
assert intervals.all?{|x| x <= 15}
|
98
|
-
assert_in_delta 10, intervals.reduce(&:+).to_f / i, 0.5
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'calculates an average poll interval based on the number of known Sidekiq processes' do
|
103
|
-
with_sidekiq_option(:average_scheduled_poll_interval, 10) do
|
104
|
-
3.times do |i|
|
105
|
-
Sidekiq.redis do |conn|
|
106
|
-
conn.sadd("processes", "process-#{i}")
|
107
|
-
conn.hset("process-#{i}", "info", nil)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
assert_equal 30, @poller.send(:scaled_poll_interval)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
data/test/test_scheduling.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require_relative 'helper'
|
3
|
-
require 'sidekiq/scheduled'
|
4
|
-
|
5
|
-
class TestScheduling < Sidekiq::Test
|
6
|
-
describe 'middleware' do
|
7
|
-
class ScheduledWorker
|
8
|
-
include Sidekiq::Worker
|
9
|
-
sidekiq_options :queue => :custom_queue
|
10
|
-
def perform(x)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
# Assume we can pass any class as time to perform_in
|
15
|
-
class TimeDuck
|
16
|
-
def to_f; 42.0 end
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'schedules jobs' do
|
20
|
-
ss = Sidekiq::ScheduledSet.new
|
21
|
-
ss.clear
|
22
|
-
|
23
|
-
assert_equal 0, ss.size
|
24
|
-
|
25
|
-
assert ScheduledWorker.perform_in(600, 'mike')
|
26
|
-
assert_equal 1, ss.size
|
27
|
-
|
28
|
-
assert ScheduledWorker.perform_in(1.month, 'mike')
|
29
|
-
assert_equal 2, ss.size
|
30
|
-
|
31
|
-
assert ScheduledWorker.perform_in(5.days.from_now, 'mike')
|
32
|
-
assert_equal 3, ss.size
|
33
|
-
|
34
|
-
q = Sidekiq::Queue.new("custom_queue")
|
35
|
-
qs = q.size
|
36
|
-
assert ScheduledWorker.perform_in(-300, 'mike')
|
37
|
-
assert_equal 3, ss.size
|
38
|
-
assert_equal qs+1, q.size
|
39
|
-
|
40
|
-
assert Sidekiq::Client.push_bulk('class' => ScheduledWorker, 'args' => [['mike'], ['mike']], 'at' => 600)
|
41
|
-
assert_equal 5, ss.size
|
42
|
-
|
43
|
-
assert ScheduledWorker.perform_in(TimeDuck.new, 'samwise')
|
44
|
-
assert_equal 6, ss.size
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'removes the enqueued_at field when scheduling' do
|
48
|
-
ss = Sidekiq::ScheduledSet.new
|
49
|
-
ss.clear
|
50
|
-
|
51
|
-
assert ScheduledWorker.perform_in(1.month, 'mike')
|
52
|
-
job = ss.first
|
53
|
-
assert job['created_at']
|
54
|
-
refute job['enqueued_at']
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|