aboutsummaryrefslogtreecommitdiffstats
path: root/activejob/lib/active_job/exceptions.rb
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2019-04-22 11:39:23 -0700
committerJohn Hawthorn <john@hawthorn.email>2019-04-22 14:53:38 -0700
commit5d9359bbc3e74f3d1433466174409411185ca49e (patch)
treecf30ab42c5b38bda721f6293c83306d9613064f4 /activejob/lib/active_job/exceptions.rb
parentcc834db1d0815744cfa173813c05d928e008e167 (diff)
downloadrails-5d9359bbc3e74f3d1433466174409411185ca49e.tar.gz
rails-5d9359bbc3e74f3d1433466174409411185ca49e.tar.bz2
rails-5d9359bbc3e74f3d1433466174409411185ca49e.zip
Use ActiveJob 5.2 retry logic for old jobs
Rails 6 introduces retries per-exception, instead of a global count of retries. Because ActiveJob 5.2 doesn't serialize the execution count per-exception, when ActiveJob 6.0 picks up an "old" job it can't know the exception count in the new format. This can also be an issue if AJ 6.0 serializes a new job with exception_executions which is later picked up by AJ 5.2, which would clear exception_executions (since it has no knowledge of it). Previously we handled this by resetting exception_executions, if it wasn't defined on a job, which could result in the worst case retrying the job 2x the times we should. This commit changes how we handle loading a legacy job: instead of resetting exception_executions, we instead will always use the global executions count. This way, jobs which only have one retry_on (and didn't have a behaviour change in AJ 6) are backwards-and-forwards-compatible with counts respected exactly. Jobs with multiple retry_on will revert to the AJ5.2 behaviour if they were ever run under AJ5.2.
Diffstat (limited to 'activejob/lib/active_job/exceptions.rb')
-rw-r--r--activejob/lib/active_job/exceptions.rb17
1 files changed, 12 insertions, 5 deletions
diff --git a/activejob/lib/active_job/exceptions.rb b/activejob/lib/active_job/exceptions.rb
index 35c1476368..8e83246303 100644
--- a/activejob/lib/active_job/exceptions.rb
+++ b/activejob/lib/active_job/exceptions.rb
@@ -49,12 +49,10 @@ module ActiveJob
# end
def retry_on(*exceptions, wait: 3.seconds, attempts: 5, queue: nil, priority: nil)
rescue_from(*exceptions) do |error|
- # Guard against jobs that were persisted before we started having individual executions counters per retry_on
- self.exception_executions ||= {}
- self.exception_executions[exceptions.to_s] = (exception_executions[exceptions.to_s] || 0) + 1
+ executions = executions_for(exceptions)
- if exception_executions[exceptions.to_s] < attempts
- retry_job wait: determine_delay(seconds_or_duration_or_algorithm: wait, executions: exception_executions[exceptions.to_s]), queue: queue, priority: priority, error: error
+ if executions < attempts
+ retry_job wait: determine_delay(seconds_or_duration_or_algorithm: wait, executions: executions), queue: queue, priority: priority, error: error
else
if block_given?
instrument :retry_stopped, error: error do
@@ -146,5 +144,14 @@ module ActiveJob
ActiveSupport::Notifications.instrument("#{name}.active_job", payload, &block)
end
+
+ def executions_for(exceptions)
+ if exception_executions
+ exception_executions[exceptions.to_s] = (exception_executions[exceptions.to_s] || 0) + 1
+ else
+ # Guard against jobs that were persisted before we started having individual executions counters per retry_on
+ executions
+ end
+ end
end
end