From a1e4c197cb12fef66530a2edfaeda75566088d1f Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Tue, 16 Aug 2016 16:01:59 -0700 Subject: Yield the job instance so you have access to things like `job.arguments` on the custom logic after retries fail --- activejob/CHANGELOG.md | 4 ++++ activejob/lib/active_job/exceptions.rb | 6 +++--- activejob/test/cases/exceptions_test.rb | 4 ++-- activejob/test/jobs/retry_job.rb | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index 12f9e1cc17..585ade7229 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,5 +1,9 @@ ## Rails 5.1.0.alpha ## +* Yield the job instance so you have access to things like `job.arguments` on the custom logic after retries fail. + + *DHH* + * Added declarative exception handling via `ActiveJob::Base.retry_on` and `ActiveJob::Base.discard_on`. Examples: diff --git a/activejob/lib/active_job/exceptions.rb b/activejob/lib/active_job/exceptions.rb index a8ff55fbe4..f8d76587ad 100644 --- a/activejob/lib/active_job/exceptions.rb +++ b/activejob/lib/active_job/exceptions.rb @@ -12,7 +12,7 @@ module ActiveJob # holding queue for inspection. # # You can also pass a block that'll be invoked if the retry attempts fail for custom logic rather than letting - # the exception bubble up. + # the exception bubble up. This block is yielded with the job instance as the first and the error instance as the second parameter. # # ==== Options # * :wait - Re-enqueues the job with a delay specified either in seconds (default: 3 seconds), @@ -28,7 +28,7 @@ module ActiveJob # class RemoteServiceJob < ActiveJob::Base # retry_on CustomAppException # defaults to 3s wait, 5 attempts # retry_on AnotherCustomAppException, wait: ->(executions) { executions * 2 } - # retry_on(YetAnotherCustomAppException) do |exception| + # retry_on(YetAnotherCustomAppException) do |job, exception| # ExceptionNotifier.caught(exception) # end # retry_on ActiveRecord::StatementInvalid, wait: 5.seconds, attempts: 3 @@ -47,7 +47,7 @@ module ActiveJob retry_job wait: determine_delay(wait), queue: queue, priority: priority else if block_given? - yield exception + yield self, exception else logger.error "Stopped retrying #{self.class} due to a #{exception}, which reoccurred on #{executions} attempts. The original exception was #{error.cause.inspect}." raise error diff --git a/activejob/test/cases/exceptions_test.rb b/activejob/test/cases/exceptions_test.rb index 30e43c99cb..9ee1dbfa0a 100644 --- a/activejob/test/cases/exceptions_test.rb +++ b/activejob/test/cases/exceptions_test.rb @@ -58,8 +58,8 @@ class ExceptionsTest < ActiveJob::TestCase test "custom handling of job that exceeds retry attempts" do perform_enqueued_jobs do - RetryJob.perform_later "CustomCatchError", 6 - assert_equal "Dealt with a job that failed to retry in a custom way", JobBuffer.last_value + RetryJob.perform_later 'CustomCatchError', 6 + assert_equal "Dealt with a job that failed to retry in a custom way after 6 attempts", JobBuffer.last_value end end diff --git a/activejob/test/jobs/retry_job.rb b/activejob/test/jobs/retry_job.rb index be20156984..c02febc50c 100644 --- a/activejob/test/jobs/retry_job.rb +++ b/activejob/test/jobs/retry_job.rb @@ -15,7 +15,7 @@ class RetryJob < ActiveJob::Base retry_on ShortWaitTenAttemptsError, wait: 1.second, attempts: 10 retry_on ExponentialWaitTenAttemptsError, wait: :exponentially_longer, attempts: 10 retry_on CustomWaitTenAttemptsError, wait: ->(executions) { executions * 2 }, attempts: 10 - retry_on(CustomCatchError) { |exception| JobBuffer.add("Dealt with a job that failed to retry in a custom way") } + retry_on(CustomCatchError) { |job, exception| JobBuffer.add("Dealt with a job that failed to retry in a custom way after #{job.arguments.second} attempts") } discard_on DiscardableError def perform(raising, attempts) -- cgit v1.2.3