sidekiq 5.0.0.beta1 → 5.0.0.beta2

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.

Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +6 -0
  3. data/Pro-Changes.md +3 -2
  4. data/bin/sidekiqload +11 -11
  5. data/lib/sidekiq/api.rb +15 -8
  6. data/lib/sidekiq/job_retry.rb +15 -12
  7. data/lib/sidekiq/processor.rb +3 -2
  8. data/lib/sidekiq/version.rb +1 -1
  9. data/lib/sidekiq/web/application.rb +1 -1
  10. data/lib/sidekiq/web/helpers.rb +2 -1
  11. data/sidekiq.gemspec +2 -2
  12. data/web/views/retry.erb +1 -1
  13. metadata +3 -67
  14. data/test/config.yml +0 -9
  15. data/test/env_based_config.yml +0 -11
  16. data/test/fake_env.rb +0 -1
  17. data/test/fixtures/en.yml +0 -2
  18. data/test/helper.rb +0 -98
  19. data/test/test_actors.rb +0 -138
  20. data/test/test_api.rb +0 -529
  21. data/test/test_cli.rb +0 -418
  22. data/test/test_client.rb +0 -266
  23. data/test/test_exception_handler.rb +0 -56
  24. data/test/test_extensions.rb +0 -115
  25. data/test/test_fetch.rb +0 -50
  26. data/test/test_launcher.rb +0 -92
  27. data/test/test_logging.rb +0 -35
  28. data/test/test_manager.rb +0 -50
  29. data/test/test_middleware.rb +0 -158
  30. data/test/test_processor.rb +0 -266
  31. data/test/test_rails.rb +0 -22
  32. data/test/test_redis_connection.rb +0 -132
  33. data/test/test_retry.rb +0 -335
  34. data/test/test_retry_exhausted.rb +0 -149
  35. data/test/test_scheduled.rb +0 -115
  36. data/test/test_scheduling.rb +0 -58
  37. data/test/test_sidekiq.rb +0 -107
  38. data/test/test_testing.rb +0 -135
  39. data/test/test_testing_fake.rb +0 -352
  40. data/test/test_testing_inline.rb +0 -93
  41. data/test/test_util.rb +0 -13
  42. data/test/test_web.rb +0 -638
  43. data/test/test_web_auth.rb +0 -54
  44. data/test/test_web_helpers.rb +0 -54
  45. data/test/test_web_sessions.rb +0 -67
@@ -1,266 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative 'helper'
3
- require 'sidekiq/fetch'
4
- require 'sidekiq/cli'
5
- require 'sidekiq/processor'
6
-
7
- class TestProcessor < Sidekiq::Test
8
- TestException = Class.new(StandardError)
9
- TEST_EXCEPTION = TestException.new("kerboom!")
10
-
11
- describe 'processor' do
12
- before do
13
- $invokes = 0
14
- @mgr = Minitest::Mock.new
15
- @mgr.expect(:options, {:queues => ['default']})
16
- @mgr.expect(:options, {:queues => ['default']})
17
- @processor = ::Sidekiq::Processor.new(@mgr)
18
- end
19
-
20
- class MockWorker
21
- include Sidekiq::Worker
22
- def perform(args)
23
- raise TEST_EXCEPTION if args == 'boom'
24
- args.pop if args.is_a? Array
25
- $invokes += 1
26
- end
27
- end
28
-
29
- def work(msg, queue='queue:default')
30
- Sidekiq::BasicFetch::UnitOfWork.new(queue, msg)
31
- end
32
-
33
- it 'processes as expected' do
34
- msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
35
- @processor.process(work(msg))
36
- assert_equal 1, $invokes
37
- end
38
-
39
- it 'executes a worker as expected' do
40
- worker = Minitest::Mock.new
41
- worker.expect(:perform, nil, [1, 2, 3])
42
- @processor.execute_job(worker, [1, 2, 3])
43
- end
44
-
45
- it 're-raises exceptions after handling' do
46
- msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
47
- re_raise = false
48
-
49
- begin
50
- @processor.process(work(msg))
51
- flunk "Expected exception"
52
- rescue TestException
53
- re_raise = true
54
- end
55
-
56
- assert_equal 0, $invokes
57
- assert re_raise, "does not re-raise exceptions after handling"
58
- end
59
-
60
- it 'does not modify original arguments' do
61
- msg = { 'class' => MockWorker.to_s, 'args' => [['myarg']] }
62
- msgstr = Sidekiq.dump_json(msg)
63
- @mgr.expect(:processor_done, nil, [@processor])
64
- @processor.process(work(msgstr))
65
- assert_equal [['myarg']], msg['args']
66
- end
67
-
68
- describe 'exception handling' do
69
- let(:errors) { [] }
70
- let(:error_handler) do
71
- proc do |exception, context|
72
- errors << { exception: exception, context: context }
73
- end
74
- end
75
-
76
- before do
77
- Sidekiq.error_handlers << error_handler
78
- end
79
-
80
- after do
81
- Sidekiq.error_handlers.pop
82
- end
83
-
84
- it 'handles invalid JSON' do
85
- ds = Sidekiq::DeadSet.new
86
- ds.clear
87
- job_hash = { 'class' => MockWorker.to_s, 'args' => ['boom'] }
88
- msg = Sidekiq.dump_json(job_hash)
89
- job = work(msg[0...-2])
90
- ds = Sidekiq::DeadSet.new
91
- assert_equal 0, ds.size
92
- begin
93
- @processor.instance_variable_set(:'@job', job)
94
- @processor.process(job)
95
- rescue JSON::ParserError
96
- end
97
- assert_equal 1, ds.size
98
- end
99
-
100
- it 'handles exceptions raised by the job' do
101
- job_hash = { 'class' => MockWorker.to_s, 'args' => ['boom'], 'jid' => '123987123' }
102
- msg = Sidekiq.dump_json(job_hash)
103
- job = work(msg)
104
- begin
105
- @processor.instance_variable_set(:'@job', job)
106
- @processor.process(job)
107
- rescue TestException
108
- end
109
- assert_equal 1, errors.count
110
- assert_instance_of TestException, errors.first[:exception]
111
- assert_equal msg, errors.first[:context][:jobstr]
112
- assert_equal job_hash['jid'], errors.first[:context][:job]['jid']
113
- end
114
-
115
- it 'handles exceptions raised by the reloader' do
116
- job_hash = { 'class' => MockWorker.to_s, 'args' => ['boom'] }
117
- msg = Sidekiq.dump_json(job_hash)
118
- @processor.instance_variable_set(:'@reloader', proc { raise TEST_EXCEPTION })
119
- job = work(msg)
120
- begin
121
- @processor.instance_variable_set(:'@job', job)
122
- @processor.process(job)
123
- rescue TestException
124
- end
125
- assert_equal 1, errors.count
126
- assert_instance_of TestException, errors.first[:exception]
127
- assert_equal msg, errors.first[:context][:jobstr]
128
- assert_equal job_hash, errors.first[:context][:job]
129
- end
130
- end
131
-
132
- describe 'acknowledgement' do
133
- class ExceptionRaisingMiddleware
134
- def initialize(raise_before_yield, raise_after_yield, skip)
135
- @raise_before_yield = raise_before_yield
136
- @raise_after_yield = raise_after_yield
137
- @skip = skip
138
- end
139
-
140
- def call(worker, item, queue)
141
- raise TEST_EXCEPTION if @raise_before_yield
142
- yield unless @skip
143
- raise TEST_EXCEPTION if @raise_after_yield
144
- end
145
- end
146
-
147
- let(:raise_before_yield) { false }
148
- let(:raise_after_yield) { false }
149
- let(:skip_job) { false }
150
- let(:worker_args) { ['myarg'] }
151
- let(:work) { MiniTest::Mock.new }
152
-
153
- before do
154
- work.expect(:queue_name, 'queue:default')
155
- work.expect(:job, Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => worker_args }))
156
- Sidekiq.server_middleware do |chain|
157
- chain.prepend ExceptionRaisingMiddleware, raise_before_yield, raise_after_yield, skip_job
158
- end
159
- end
160
-
161
- after do
162
- Sidekiq.server_middleware do |chain|
163
- chain.remove ExceptionRaisingMiddleware
164
- end
165
- work.verify
166
- end
167
-
168
- describe 'middleware throws an exception before processing the work' do
169
- let(:raise_before_yield) { true }
170
-
171
- it 'acks the job' do
172
- work.expect(:acknowledge, nil)
173
- begin
174
- @processor.process(work)
175
- flunk "Expected #process to raise exception"
176
- rescue TestException
177
- end
178
- end
179
- end
180
-
181
- describe 'middleware throws an exception after processing the work' do
182
- let(:raise_after_yield) { true }
183
-
184
- it 'acks the job' do
185
- work.expect(:acknowledge, nil)
186
- begin
187
- @processor.process(work)
188
- flunk "Expected #process to raise exception"
189
- rescue TestException
190
- end
191
- end
192
- end
193
-
194
- describe 'middleware decides to skip work' do
195
- let(:skip_job) { true }
196
-
197
- it 'acks the job' do
198
- work.expect(:acknowledge, nil)
199
- @mgr.expect(:processor_done, nil, [@processor])
200
- @processor.process(work)
201
- end
202
- end
203
-
204
- describe 'worker raises an exception' do
205
- let(:worker_args) { ['boom'] }
206
-
207
- it 'acks the job' do
208
- work.expect(:acknowledge, nil)
209
- begin
210
- @processor.process(work)
211
- flunk "Expected #process to raise exception"
212
- rescue TestException
213
- end
214
- end
215
- end
216
-
217
- describe 'everything goes well' do
218
- it 'acks the job' do
219
- work.expect(:acknowledge, nil)
220
- @mgr.expect(:processor_done, nil, [@processor])
221
- @processor.process(work)
222
- end
223
- end
224
- end
225
-
226
- describe 'stats' do
227
- before do
228
- Sidekiq.redis {|c| c.flushdb }
229
- end
230
-
231
- describe 'when successful' do
232
- let(:processed_today_key) { "stat:processed:#{Time.now.utc.strftime("%Y-%m-%d")}" }
233
-
234
- def successful_job
235
- msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
236
- @mgr.expect(:processor_done, nil, [@processor])
237
- @processor.process(work(msg))
238
- end
239
-
240
- it 'increments processed stat' do
241
- Sidekiq::Processor::PROCESSED.value = 0
242
- successful_job
243
- assert_equal 1, Sidekiq::Processor::PROCESSED.value
244
- end
245
- end
246
-
247
- describe 'when failed' do
248
- let(:failed_today_key) { "stat:failed:#{Time.now.utc.strftime("%Y-%m-%d")}" }
249
-
250
- def failed_job
251
- msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
252
- begin
253
- @processor.process(work(msg))
254
- rescue TestException
255
- end
256
- end
257
-
258
- it 'increments failed stat' do
259
- Sidekiq::Processor::FAILURE.value = 0
260
- failed_job
261
- assert_equal 1, Sidekiq::Processor::FAILURE.value
262
- end
263
- end
264
- end
265
- end
266
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative 'helper'
3
-
4
- $HAS_AJ = true
5
- begin
6
- require 'active_job'
7
- rescue LoadError
8
- $HAS_AJ = false
9
- end
10
-
11
- class TestRails < Sidekiq::Test
12
-
13
- describe 'ActiveJob' do
14
- it 'does not allow Sidekiq::Worker in AJ::Base classes' do
15
- ex = assert_raises ArgumentError do
16
- c = Class.new(ActiveJob::Base)
17
- c.send(:include, Sidekiq::Worker)
18
- end
19
- assert_includes ex.message, "cannot include"
20
- end if $HAS_AJ
21
- end
22
- end
@@ -1,132 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative 'helper'
3
-
4
- class TestRedisConnection < Sidekiq::Test
5
-
6
- describe ".create" do
7
-
8
- it "creates a pooled redis connection" do
9
- pool = Sidekiq::RedisConnection.create
10
- assert_equal Redis, pool.checkout.class
11
- end
12
-
13
- describe "network_timeout" do
14
- it "sets a custom network_timeout if specified" do
15
- pool = Sidekiq::RedisConnection.create(:network_timeout => 8)
16
- redis = pool.checkout
17
-
18
- assert_equal 8, redis.client.timeout
19
- end
20
-
21
- it "uses the default network_timeout if none specified" do
22
- pool = Sidekiq::RedisConnection.create
23
- redis = pool.checkout
24
-
25
- assert_equal 5, redis.client.timeout
26
- end
27
- end
28
-
29
- describe "namespace" do
30
- it "uses a given :namespace set by a symbol key" do
31
- pool = Sidekiq::RedisConnection.create(:namespace => "xxx")
32
- assert_equal "xxx", pool.checkout.namespace
33
- end
34
-
35
- it "uses a given :namespace set by a string key" do
36
- pool = Sidekiq::RedisConnection.create("namespace" => "xxx")
37
- assert_equal "xxx", pool.checkout.namespace
38
- end
39
-
40
- it "uses given :namespace over :namespace from Sidekiq.options" do
41
- Sidekiq.options[:namespace] = "xxx"
42
- pool = Sidekiq::RedisConnection.create(:namespace => "yyy")
43
- assert_equal "yyy", pool.checkout.namespace
44
- end
45
- end
46
-
47
- describe "socket path" do
48
- it "uses a given :path" do
49
- pool = Sidekiq::RedisConnection.create(:path => "/var/run/redis.sock")
50
- assert_equal "unix", pool.checkout.client.scheme
51
- assert_equal "redis:///var/run/redis.sock/0", pool.checkout.client.id
52
- end
53
-
54
- it "uses a given :path and :db" do
55
- pool = Sidekiq::RedisConnection.create(:path => "/var/run/redis.sock", :db => 8)
56
- assert_equal "unix", pool.checkout.client.scheme
57
- assert_equal "redis:///var/run/redis.sock/8", pool.checkout.client.id
58
- end
59
- end
60
-
61
- describe "pool_timeout" do
62
- it "uses a given :timeout over the default of 1" do
63
- pool = Sidekiq::RedisConnection.create(:pool_timeout => 5)
64
-
65
- assert_equal 5, pool.instance_eval{ @timeout }
66
- end
67
-
68
- it "uses the default timeout of 1 if no override" do
69
- pool = Sidekiq::RedisConnection.create
70
-
71
- assert_equal 1, pool.instance_eval{ @timeout }
72
- end
73
- end
74
- end
75
-
76
- describe ".determine_redis_provider" do
77
-
78
- before do
79
- @old_env = ENV.to_hash
80
- end
81
-
82
- after do
83
- ENV.update(@old_env)
84
- end
85
-
86
- def with_env_var(var, uri, skip_provider=false)
87
- vars = ['REDISTOGO_URL', 'REDIS_PROVIDER', 'REDIS_URL'] - [var]
88
- vars.each do |v|
89
- next if skip_provider
90
- ENV[v] = nil
91
- end
92
- ENV[var] = uri
93
- assert_equal uri, Sidekiq::RedisConnection.__send__(:determine_redis_provider)
94
- ENV[var] = nil
95
- end
96
-
97
- describe "with REDISTOGO_URL and a parallel REDIS_PROVIDER set" do
98
- it "sets connection URI to the provider" do
99
- uri = 'redis://sidekiq-redis-provider:6379/0'
100
- provider = 'SIDEKIQ_REDIS_PROVIDER'
101
-
102
- ENV['REDIS_PROVIDER'] = provider
103
- ENV[provider] = uri
104
- ENV['REDISTOGO_URL'] = 'redis://redis-to-go:6379/0'
105
- with_env_var provider, uri, true
106
-
107
- ENV[provider] = nil
108
- end
109
- end
110
-
111
- describe "with REDIS_PROVIDER set" do
112
- it "sets connection URI to the provider" do
113
- uri = 'redis://sidekiq-redis-provider:6379/0'
114
- provider = 'SIDEKIQ_REDIS_PROVIDER'
115
-
116
- ENV['REDIS_PROVIDER'] = provider
117
- ENV[provider] = uri
118
-
119
- with_env_var provider, uri, true
120
-
121
- ENV[provider] = nil
122
- end
123
- end
124
-
125
- describe "with REDIS_URL set" do
126
- it "sets connection URI to custom uri" do
127
- with_env_var 'REDIS_URL', 'redis://redis-uri:6379/0'
128
- end
129
- end
130
-
131
- end
132
- end
@@ -1,335 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: true
3
- require_relative 'helper'
4
- require 'sidekiq/scheduled'
5
- require 'sidekiq/job_retry'
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::JobRetry.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 'retries with a nil worker' do
30
- assert_raises RuntimeError do
31
- handler.global(job, 'default') do
32
- raise "boom"
33
- end
34
- end
35
- assert_equal 1, Sidekiq::RetrySet.new.size
36
- end
37
-
38
- it 'allows disabling retry' do
39
- assert_raises RuntimeError do
40
- handler.local(worker, job('retry' => false), 'default') do
41
- raise "kerblammo!"
42
- end
43
- end
44
- assert_equal 0, Sidekiq::RetrySet.new.size
45
- end
46
-
47
- it 'allows a numeric retry' do
48
- assert_raises RuntimeError do
49
- handler.local(worker, job('retry' => 2), 'default') do
50
- raise "kerblammo!"
51
- end
52
- end
53
- assert_equal 1, Sidekiq::RetrySet.new.size
54
- assert_equal 0, Sidekiq::DeadSet.new.size
55
- end
56
-
57
- it 'allows 0 retry => no retry and dead queue' do
58
- assert_raises RuntimeError do
59
- handler.local(worker, job('retry' => 0), 'default') do
60
- raise "kerblammo!"
61
- end
62
- end
63
- assert_equal 0, Sidekiq::RetrySet.new.size
64
- assert_equal 1, Sidekiq::DeadSet.new.size
65
- end
66
-
67
- it 'handles zany characters in error message, #1705' do
68
- skip 'skipped! test requires ruby 2.1+' if RUBY_VERSION <= '2.1.0'
69
-
70
- assert_raises RuntimeError do
71
- handler.local(worker, job, 'default') do
72
- raise "kerblammo! #{195.chr}"
73
- end
74
- end
75
- assert_equal "kerblammo! �", job["error_message"]
76
- end
77
-
78
-
79
- it 'allows a max_retries option in initializer' do
80
- max_retries = 7
81
- 1.upto(max_retries + 1) do
82
- assert_raises RuntimeError do
83
- handler(:max_retries => max_retries).local(worker, job, 'default') do
84
- raise "kerblammo!"
85
- end
86
- end
87
- end
88
-
89
- assert_equal max_retries, Sidekiq::RetrySet.new.size
90
- assert_equal 1, Sidekiq::DeadSet.new.size
91
- end
92
-
93
- it 'saves backtraces' do
94
- c = nil
95
- assert_raises RuntimeError do
96
- handler.local(worker, job('backtrace' => true), 'default') do
97
- c = caller(0); raise "kerblammo!"
98
- end
99
- end
100
- assert job["error_backtrace"]
101
- assert_equal c[0], job["error_backtrace"][0]
102
- end
103
-
104
- it 'saves partial backtraces' do
105
- c = nil
106
- assert_raises RuntimeError do
107
- handler.local(worker, job('backtrace' => 3), 'default') do
108
- c = caller(0)[0...3]; raise "kerblammo!"
109
- end
110
- end
111
- assert job["error_backtrace"]
112
- assert_equal c, job["error_backtrace"]
113
- assert_equal 3, c.size
114
- end
115
-
116
- it 'handles a new failed message' do
117
- assert_raises RuntimeError do
118
- handler.local(worker, job, 'default') do
119
- raise "kerblammo!"
120
- end
121
- end
122
- assert_equal 'default', job["queue"]
123
- assert_equal 'kerblammo!', job["error_message"]
124
- assert_equal 'RuntimeError', job["error_class"]
125
- assert_equal 0, job["retry_count"]
126
- refute job["error_backtrace"]
127
- assert job["failed_at"]
128
- end
129
-
130
- it 'shuts down without retrying work-in-progress, which will resume' do
131
- rs = Sidekiq::RetrySet.new
132
- assert_equal 0, rs.size
133
- msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
134
- assert_raises Sidekiq::Shutdown do
135
- handler.local(worker, msg, 'default') do
136
- raise Sidekiq::Shutdown
137
- end
138
- end
139
- assert_equal 0, rs.size
140
- end
141
-
142
- it 'shuts down cleanly when shutdown causes exception' do
143
- skip('Not supported in Ruby < 2.1.0') if RUBY_VERSION < '2.1.0'
144
-
145
- rs = Sidekiq::RetrySet.new
146
- assert_equal 0, rs.size
147
- msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
148
- assert_raises Sidekiq::Shutdown do
149
- handler.local(worker, msg, 'default') do
150
- begin
151
- raise Sidekiq::Shutdown
152
- rescue Interrupt
153
- raise "kerblammo!"
154
- end
155
- end
156
- end
157
- assert_equal 0, rs.size
158
- end
159
-
160
- it 'shuts down cleanly when shutdown causes chained exceptions' do
161
- skip('Not supported in Ruby < 2.1.0') if RUBY_VERSION < '2.1.0'
162
-
163
- rs = Sidekiq::RetrySet.new
164
- assert_equal 0, rs.size
165
- assert_raises Sidekiq::Shutdown do
166
- handler.local(worker, job, 'default') do
167
- begin
168
- raise Sidekiq::Shutdown
169
- rescue Interrupt
170
- begin
171
- raise "kerblammo!"
172
- rescue
173
- raise "kablooie!"
174
- end
175
- end
176
- end
177
- end
178
- assert_equal 0, rs.size
179
- end
180
-
181
- it 'allows a retry queue' do
182
- assert_raises RuntimeError do
183
- handler.local(worker, job("retry_queue" => 'retryx'), 'default') do
184
- raise "kerblammo!"
185
- end
186
- end
187
- assert_equal 'retryx', job["queue"]
188
- assert_equal 'kerblammo!', job["error_message"]
189
- assert_equal 'RuntimeError', job["error_class"]
190
- assert_equal 0, job["retry_count"]
191
- refute job["error_backtrace"]
192
- assert job["failed_at"]
193
- end
194
-
195
- it 'handles a recurring failed message' do
196
- now = Time.now.to_f
197
- msg = {"queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>10}
198
- assert_raises RuntimeError do
199
- handler.local(worker, job(msg), 'default') do
200
- raise "kerblammo!"
201
- end
202
- end
203
- assert_equal 'default', job["queue"]
204
- assert_equal 'kerblammo!', job["error_message"]
205
- assert_equal 'RuntimeError', job["error_class"]
206
- assert_equal 11, job["retry_count"]
207
- assert job["failed_at"]
208
- end
209
-
210
- it 'throws away old messages after too many retries (using the default)' do
211
- q = Sidekiq::Queue.new
212
- rs = Sidekiq::RetrySet.new
213
- ds = Sidekiq::DeadSet.new
214
- assert_equal 0, q.size
215
- assert_equal 0, rs.size
216
- assert_equal 0, ds.size
217
- now = Time.now.to_f
218
- msg = {"queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>25}
219
- assert_raises RuntimeError do
220
- handler.local(worker, job(msg), 'default') do
221
- raise "kerblammo!"
222
- end
223
- end
224
- assert_equal 0, q.size
225
- assert_equal 0, rs.size
226
- assert_equal 1, ds.size
227
- end
228
-
229
- describe "custom retry delay" do
230
- before do
231
- @old_logger = Sidekiq.logger
232
- @tmp_log_path = '/tmp/sidekiq-retries.log'
233
- Sidekiq.logger = Logger.new(@tmp_log_path)
234
- end
235
-
236
- after do
237
- Sidekiq.logger = @old_logger
238
- Sidekiq.options.delete(:logfile)
239
- File.unlink @tmp_log_path if File.exist?(@tmp_log_path)
240
- end
241
-
242
- class CustomWorkerWithoutException
243
- include Sidekiq::Worker
244
-
245
- sidekiq_retry_in do |count|
246
- count * 2
247
- end
248
- end
249
-
250
- class CustomWorkerWithException
251
- include Sidekiq::Worker
252
-
253
- sidekiq_retry_in do |count, exception|
254
- case exception
255
- when ArgumentError
256
- count * 4
257
- else
258
- count * 2
259
- end
260
- end
261
- end
262
-
263
- class ErrorWorker
264
- include Sidekiq::Worker
265
-
266
- sidekiq_retry_in do |count|
267
- count / 0
268
- end
269
- end
270
-
271
- it "retries with a default delay" do
272
- refute_equal 4, handler.__send__(:delay_for, worker, 2, StandardError.new)
273
- end
274
-
275
- it "retries with a custom delay and exception 1" do
276
- assert_equal 8, handler.__send__(:delay_for, CustomWorkerWithException, 2, ArgumentError.new)
277
- end
278
-
279
- it "retries with a custom delay and exception 2" do
280
- assert_equal 4, handler.__send__(:delay_for, CustomWorkerWithException, 2, StandardError.new)
281
- end
282
-
283
- it "retries with a custom delay without exception" do
284
- assert_equal 4, handler.__send__(:delay_for, CustomWorkerWithoutException, 2, StandardError.new)
285
- end
286
-
287
- it "falls back to the default retry on exception" do
288
- refute_equal 4, handler.__send__(:delay_for, ErrorWorker, 2, StandardError.new)
289
- assert_match(/Failure scheduling retry using the defined `sidekiq_retry_in`/,
290
- File.read(@tmp_log_path), 'Log entry missing for sidekiq_retry_in')
291
- end
292
- end
293
-
294
- describe 'handles errors withouth cause' do
295
- before do
296
- @error = nil
297
- begin
298
- raise ::StandardError, 'Error'
299
- rescue ::StandardError => e
300
- @error = e
301
- end
302
- end
303
-
304
- it "does not recurse infinitely checking if it's a shutdown" do
305
- assert(!Sidekiq::JobRetry.new.send(
306
- :exception_caused_by_shutdown?, @error))
307
- end
308
- end
309
-
310
- describe 'handles errors with circular causes' do
311
- before do
312
- @error = nil
313
- begin
314
- begin
315
- raise ::StandardError, 'Error 1'
316
- rescue ::StandardError => e1
317
- begin
318
- raise ::StandardError, 'Error 2'
319
- rescue ::StandardError
320
- raise e1
321
- end
322
- end
323
- rescue ::StandardError => e
324
- @error = e
325
- end
326
- end
327
-
328
- it "does not recurse infinitely checking if it's a shutdown" do
329
- assert(!Sidekiq::JobRetry.new.send(
330
- :exception_caused_by_shutdown?, @error))
331
- end
332
- end
333
- end
334
-
335
- end