-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
make retry() more flexible #19331
make retry() more flexible #19331
Conversation
event of an exception. If `retry_on` is a `Type` then retry only | ||
for exceptions of that type. If `retry_on` is a function | ||
`test_error(::Exception) -> Bool` then retry only if it is true. | ||
Returns a lambda that retries function `f` in the event of an exception. If |
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.
Maybe use "anonymous function" in place of "lambda"? I did a quick search of the Julia docs and this looks like one of two uses of "lambda" to mean anonymous function. I think anonymous function is already used more often, and is easier to guess the meaning of.
77a97fc
to
7f4b292
Compare
"lambda" changed to "anonymous function". anything else? |
@samoconnor @amitmurthy this modifies your code. any comments? |
I am not a fan of this change. If we really need such detailed customization it is probably better to implement a The current signature should be supported via a |
Rather than exposing all the constants, I would prefer to have, say, 3 selectable configurable strategies, each with a fixed set of constants. The current values are intended to work well for retrying due to network congestion/failure. I'm interested in what the other use cases are. It looks like the jitter used to be +/- 0% to 20%, but is now + 0% to 10%. Why reduce the default range? To my eye, the pattern of defining DEFAULT_UPPER_CASE_CONSTANTS and then using them to set kw arg defaults is clumsy and redundant. If I'm looking at the signature of |
@amitmurthy i've refactored @samoconnor my use case is to make my code fault tolerant to network hard drive failures, so my retries need to happen on the time scale of hours not seconds. in general i just don't think it's a good idea to have so many parameters hard coded. note that tests are currently failing due to a bootstrapping error during the build process. below is the error i'm getting. any ideas? i've never encountered a bootstrapping error before:
|
d674d3c
to
8bf9edd
Compare
@@ -993,6 +993,7 @@ export | |||
error, | |||
rethrow, | |||
retry, | |||
default_retry_check, |
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.
this is a really messy name to be exporting
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.
@amitmurthy i'd be happy not exporting default_retry_check
. what do you think?
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.
definitely don't want to export this. would a user need to call it?
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.
users would need to call default_retry_check
only if they want to change it's keyword arguments. see the tests for examples.
if your objection is the length of the symbol, there is ample precedent:
julia> idx=sortperm(map(x->length(string(x)),names(Base)));
julia> names(Base)[idx[end-20:end]]
21-element Array{Symbol,1}:
:specialized_binary
:task_local_storage
:AbstractSparseArray
:broadcast!_function
:broadcast_setindex!
:default_worker_pool
:get_zero_subnormals
:pointer_from_objref
:set_zero_subnormals
:AbstractSparseMatrix
:AbstractSparseVector
:RoundNearestTiesAway
:blas_set_num_threads
:InvalidStateException
:ProcessExitedException
:get_bigfloat_precision
:set_bigfloat_precision
:with_bigfloat_precision
:unsafe_pointer_to_objref
:specialized_bitwise_unary
:specialized_bitwise_binary
note that in the parallel realm there is already default_worker_pool
. what would you think of default_check
and default_pool
, respectively, instead?
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.
don't think we should be exporting default_worker_pool
either, at least not under that name
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.
Some of those are long type names and are ok. Most of the long names with underscores we have been working to eliminate. A long underscored name is a strong indication that you are exposing insufficiently well factored concepts. This is worse for verbs than for nouns.
bootstrapping error now fixed by removing the use of |
@amitmurthy i've removed the export of |
This is squarely in @amitmurthy's court – up to you if you want to merge or not. |
|
||
# Examples | ||
``` | ||
map(retry(x->x^2, (s,e)->default_retry_check(s,e,n=47)), 1:5) |
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.
should this be formatted as an doctest with the output visible?
@bjarthur thanks for your patience. Thinking some more, there may be a better way to do this. We could use a standard iterator interface for specifying delays which adds to the overall flexibility. So we have,
if
You can remove the uppercase constant definitions. In addition to standard More complex strategies including retrying for different intervals depending on the type of error encountered can be specified via custom |
@amitmurthy i've implemented one of the travis builds stalled, otherwise the tests passed. |
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.
We should export ExponentialBackOff
.
if i > n || try retry_on(e) end !== true | ||
rethrow(e) | ||
done(delays, state) && rethrow(e) | ||
if check != nothing |
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.
!==
@@ -158,8 +158,6 @@ function wrap_on_error(f, on_error; capture_data=false) | |||
end | |||
end | |||
|
|||
wrap_retry(f, retry_on, n, max_delay) = retry(f, retry_on; n=n, max_delay=max_delay) | |||
|
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 reason for this was a StackOverflow
error being thrown when done inline. I assume you are not seeing that now.
retry_on=retry_on, | ||
retry_n=retry_n, | ||
retry_max_delay=retry_max_delay) | ||
on_error = on_error, retry_delays = retry_delays[2:end], retry_check = retry_check) |
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 think this may not work if retry_delays is of type ExponentialBackOff? I think the retry logic in pmap will need a different approach. We can tackle it as a separate issue.
|
||
""" | ||
retry(f, [retry_on]; n=1, max_delay=10.0) -> Function | ||
ExponentialBackOff(; n=1, first_delay=0.05, max_delay=10.0, factor=5.0, jitter=0.1) |
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.
if this does get exported, then be sure to add it to the stdlib doc index
requested changes made. all tests pass. |
Thanks. Can you add a line to NEWS.md with a short description of this change? |
retry as it is is GREAT! however, it's not flexible enough for my needs. this PR simply hoists all of the arbitrary hard-coded constants up to keyword arguments. it also add the ability to display a custom message at each retry. lastly it interpolates the global default values into the docstring so the two don't get out of sync.
@amitmurthy @samoconnor