diff --git a/lib/sidekiq/middleware/server/retry_jobs.rb b/lib/sidekiq/middleware/server/retry_jobs.rb index 55352046..1bc82167 100644 --- a/lib/sidekiq/middleware/server/retry_jobs.rb +++ b/lib/sidekiq/middleware/server/retry_jobs.rb @@ -14,7 +14,8 @@ module Sidekiq # 3. after a few days, a developer deploys a fix. the message is # reprocessed successfully. # 4. if 3 never happens, sidekiq will eventually give up and throw the - # message away. + # message away. If the worker defines a method called 'exhausted', this + # will be called before throwing the message away. # # A message looks like: # @@ -82,8 +83,10 @@ module Sidekiq end else # Goodbye dear message, you (re)tried your best I'm sure. + worker.exhausted(*msg['args']) if worker.respond_to?(:exhausted) logger.debug { "Dropping message after hitting the retry maximum: #{msg}" } end + raise e end diff --git a/test/test_retry.rb b/test/test_retry.rb index 1331a285..4546544b 100644 --- a/test/test_retry.rb +++ b/test/test_retry.rb @@ -167,6 +167,18 @@ class TestRetry < MiniTest::Unit::TestCase # 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