-
Notifications
You must be signed in to change notification settings - Fork 21.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Proc as a type for ActiveJob retry_on attempts #46245
base: main
Are you sure you want to change the base?
Conversation
ActiveJob retry_on allowed the wait option to be set as a Proc that calculates the wait but did not give the same option for attempts. attempts could be set to only a number of times to attempt or unlimited. However, jobs sometimes need different logic than number of executions to determine if they should try again. This commit adds support for setting attempts to a Proc that returns either true or false. On true the retry will occur. As a an example: retry_on ProcRetryError, attempts: ->(executions) { executions < 2 }
@@ -25,8 +25,9 @@ module ClassMethods | |||
# as a computing proc that takes the number of executions so far as an argument, or as a symbol reference of | |||
# <tt>:exponentially_longer</tt>, which applies the wait algorithm of <tt>((executions**4) + (Kernel.rand * (executions**4) * jitter)) + 2</tt> | |||
# (first wait ~3s, then ~18s, then ~83s, etc) | |||
# * <tt>:attempts</tt> - Re-enqueues the job the specified number of times (default: 5 attempts) or a symbol reference of <tt>:unlimited</tt> | |||
# to retry the job until it succeeds | |||
# * <tt>:attempts</tt> - Re-enqueues the job either the specified number of times (default: 5 attempts), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it is clear from the name that it is meant to return a boolean? I could see someone returning 0 and running into trouble because it is truthy.
Would it make sense to have an alternate mutually exclusive parameter with a different name, rather than reusing attempts
? Something like attempt_again
or reattempt
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, that is a good point. It does become less clear. Originally I was just going to make the proc return a number to be compared... but then I thought it would be good to add more flexibility by making it return true/false.
So two questions:
- What do you think of still allowing a Proc for
attempts
but making that proc return a number so it still gives flexibility to generate that number from something instead of passing in an Int? - If that happens do you think I should also add support for :reattempt that is true/false? I don't need it for what I'm doing but I'd be happy to add it for the greater flexibility for others in the future. And if I do should it be part of this PR or a separate one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @rosew great PR! I just opened #46261 and was pointed over to this. I'd be in strong support of:
What do you think of still allowing a Proc for attempts but making that proc return a number so it still gives flexibility to generate that number from something instead of passing in an Int?
That would give good flexibility for most cases imo.
In #46261 I had intended to pass the job instance to the attempts proc, to allow callers to dynamically specify the desired number of attempts by doing something like
class MyJob < ActiveJob::Base
retry_on CustomRetryException, attempts: ->(job){ job.arguments.last[:retries] || 5 }
def perform(retries:)
# job implementation
end
end
MyJob.perform_later(retries: 10)
MyJob.perform_later(retries: 1)
What are your thoughts on doing something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main reason I passed in executions was because it mirrored the behavior of the other Proc accepted for delay. I don't have a strong opinion either way on if this would be a good case to break from the current pattern or not.
I do see how my method can allow it to be customized at the Class level where yours can allow it to be customized at the instance level.
I'd love thoughts from rails maintainers on how close we should stick to the other proc pattern and/or if there are reasons not to pass the into the proc.
Motivation / Background
This Pull Request has been created because I needed
retry_on attempts:
to use more complex logic than an Integer.In my specific case I was creating a concern for Jobs that would use
retry_on
to allow jobs to quietly fail and retry. The concern was going to use a method to allow attempts to be customized in individual jobs.However this ran into a state where the method needed to be defined and run when the concern was included instead of being available later in the job. It would be very fragile to have to define the method before including the concern. This lead to me to looking at if attempts accepted anything besides an integer. It did not but I saw there was already a pattern in place for wait to accept a Proc. I thought if that pattern was repeated for attempts than it would allow more flexibility for configuring attempts.
My original thought was to have the Proc for attempts return a number similar to what the Proc for wait does. However, on thinking about it I decided that still did not leave much flexibility because attempts would still be determined by a number. Instead I switched it to return true/false so if the next attempt occurred could be determined by whatever logic was implemented in the Proc.
Detail
This Pull Request changes ActiveJob retry_on attempts so it will accept a Proc.
ActiveJob retry_on allowed the wait option to be set as a Proc that calculates the wait but did not give the same option for attempts. attempts could be set to only a number of times to attempt or unlimited. However, jobs sometimes need different logic than number of executions to determine if they should try again.
This PR adds support for setting attempts to a Proc that returns either true or false. On true the retry will occur.
As a an example:
Additional information
Checklist
Before submitting the PR make sure the following are checked:
[Fix #issue-number]
main
(if not - rebase it).