1
0
Fork 0
mirror of https://github.com/mperham/sidekiq.git synced 2022-11-09 13:52:34 -05:00
mperham--sidekiq/test/test_retry.rb
James Kassemi 172434d459 Call 'exhausted' worker method after retries
When the maximum number of retries is hit and the message is about
to be thrown away, give the option of allowing the worker to say
goodbye by defining an 'exhausted' method on the worker.
2013-03-18 15:20:28 -06:00

206 lines
7.5 KiB
Ruby

require 'helper'
require 'sidekiq/scheduled'
require 'sidekiq/middleware/server/retry_jobs'
class TestRetry < MiniTest::Unit::TestCase
describe 'middleware' do
before do
@redis = MiniTest::Mock.new
# Ugh, this is terrible.
Sidekiq.instance_variable_set(:@redis, @redis)
def @redis.with; yield self; end
end
it 'allows disabling retry' do
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => false }
msg2 = msg.dup
handler = Sidekiq::Middleware::Server::RetryJobs.new
assert_raises RuntimeError do
handler.call('', msg2, 'default') do
raise "kerblammo!"
end
end
assert_equal msg, msg2
end
it 'allows a numeric retry' do
@redis.expect :zadd, 1, ['retry', String, String]
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => 2 }
msg2 = msg.dup
handler = Sidekiq::Middleware::Server::RetryJobs.new
assert_raises RuntimeError do
handler.call('', msg2, 'default') do
raise "kerblammo!"
end
end
msg2.delete('failed_at')
assert_equal({"class"=>"Bob", "args"=>[1, 2, "foo"], "retry"=>2, "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "retry_count"=>0}, msg2)
@redis.verify
end
it 'saves backtraces' do
@redis.expect :zadd, 1, ['retry', String, String]
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true, 'backtrace' => true }
handler = Sidekiq::Middleware::Server::RetryJobs.new
c = nil
assert_raises RuntimeError do
handler.call('', msg, 'default') do
c = caller(0); raise "kerblammo!"
end
end
assert msg["error_backtrace"]
assert_equal c[0], msg["error_backtrace"][0]
@redis.verify
end
it 'saves partial backtraces' do
@redis.expect :zadd, 1, ['retry', String, String]
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true, 'backtrace' => 3 }
handler = Sidekiq::Middleware::Server::RetryJobs.new
c = nil
assert_raises RuntimeError do
handler.call('', msg, 'default') do
c = caller(0)[0..3]; raise "kerblammo!"
end
end
assert msg["error_backtrace"]
assert_equal c, msg["error_backtrace"]
end
it 'handles a new failed message' do
@redis.expect :zadd, 1, ['retry', String, String]
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
handler = Sidekiq::Middleware::Server::RetryJobs.new
assert_raises RuntimeError do
handler.call('', msg, 'default') do
raise "kerblammo!"
end
end
assert_equal 'default', msg["queue"]
assert_equal 'kerblammo!', msg["error_message"]
assert_equal 'RuntimeError', msg["error_class"]
assert_equal 0, msg["retry_count"]
refute msg["error_backtrace"]
assert msg["failed_at"]
@redis.verify
end
it 'allows a retry queue' do
@redis.expect :zadd, 1, ['retry', String, String]
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true, 'retry_queue' => 'retry' }
handler = Sidekiq::Middleware::Server::RetryJobs.new
assert_raises RuntimeError do
handler.call('', msg, 'default') do
raise "kerblammo!"
end
end
assert_equal 'retry', msg["queue"]
assert_equal 'kerblammo!', msg["error_message"]
assert_equal 'RuntimeError', msg["error_class"]
assert_equal 0, msg["retry_count"]
refute msg["error_backtrace"]
assert msg["failed_at"]
@redis.verify
end
it 'handles a recurring failed message' do
@redis.expect :zadd, 1, ['retry', String, String]
now = Time.now.utc
msg = {"class"=>"Bob", "args"=>[1, 2, "foo"], 'retry' => true, "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>10}
handler = Sidekiq::Middleware::Server::RetryJobs.new
assert_raises RuntimeError do
handler.call('', msg, 'default') do
raise "kerblammo!"
end
end
assert_equal 'default', msg["queue"]
assert_equal 'kerblammo!', msg["error_message"]
assert_equal 'RuntimeError', msg["error_class"]
assert_equal 11, msg["retry_count"]
assert msg["failed_at"]
@redis.verify
end
it 'handles a recurring failed message before reaching user-specifed max' do
@redis.expect :zadd, 1, ['retry', String, String]
now = Time.now.utc
msg = {"class"=>"Bob", "args"=>[1, 2, "foo"], 'retry' => 10, "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>8}
handler = Sidekiq::Middleware::Server::RetryJobs.new
assert_raises RuntimeError do
handler.call('', msg, 'default') do
raise "kerblammo!"
end
end
assert_equal 'default', msg["queue"]
assert_equal 'kerblammo!', msg["error_message"]
assert_equal 'RuntimeError', msg["error_class"]
assert_equal 9, msg["retry_count"]
assert msg["failed_at"]
@redis.verify
end
it 'throws away old messages after too many retries (using the default)' do
now = Time.now.utc
msg = {"class"=>"Bob", "args"=>[1, 2, "foo"], "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry"=>true, "retry_count"=>25}
@redis.expect :zadd, 1, [ 'retry', String, String ]
handler = Sidekiq::Middleware::Server::RetryJobs.new
assert_raises RuntimeError do
handler.call('', msg, 'default') do
raise "kerblammo!"
end
end
# MiniTest can't assert that a method call did NOT happen!?
assert_raises(MockExpectationError) { @redis.verify }
end
it 'throws away old messages after too many retries (using user-specified max)' do
now = Time.now.utc
msg = {"class"=>"Bob", "args"=>[1, 2, "foo"], "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry"=>3, "retry_count"=>3}
@redis.expect :zadd, 1, [ 'retry', String, String ]
handler = Sidekiq::Middleware::Server::RetryJobs.new
assert_raises RuntimeError do
handler.call('', msg, 'default') do
raise "kerblammo!"
end
end
# MiniTest can't assert that a method call did NOT happen!?
assert_raises(MockExpectationError) { @redis.verify }
end
it 'calls exhausted method on worker after too many retries if available' do
msg = {"class"=>"Bob", "args"=>[1, 2, "foo"], "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>Time.now.utc, "retry"=>3, "retry_count"=>3}
worker = MiniTest::Mock.new
worker.expect :exhausted, true, [1, 2, "foo"]
handler = Sidekiq::Middleware::Server::RetryJobs.new
assert_raises RuntimeError do
handler.call(worker, msg, 'default') do
raise "kerblammo!"
end
end
end
end
describe 'poller' do
before do
@redis = MiniTest::Mock.new
Sidekiq.instance_variable_set(:@redis, @redis)
def @redis.with; yield self; end
end
it 'should poll like a bad mother...SHUT YO MOUTH' do
fake_msg = Sidekiq.dump_json({ 'class' => 'Bob', 'args' => [1,2], 'queue' => 'someq' })
@redis.expect :multi, [[fake_msg], 1], []
@redis.expect :multi, [[], nil], []
@redis.expect :multi, [[], nil], []
@redis.expect :multi, [[], nil], []
inst = Sidekiq::Scheduled::Poller.new
inst.poll
@redis.verify
end
end
end