Skip to content
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

Retry on specific exception type 84 #135

Merged
merged 9 commits into from
Feb 10, 2020
Merged

Retry on specific exception type 84 #135

merged 9 commits into from
Feb 10, 2020

Conversation

ewjoachim
Copy link
Member

@ewjoachim ewjoachim commented Jan 31, 2020

Fixes #84

Pair programmed with @emmanuelleq

Successful PR Checklist:

  • Tests
  • Documentation (optionally: run spell checking)
  • Had a good time contributing? (if not, feel free to give some feedback)

@codecov-io
Copy link

codecov-io commented Jan 31, 2020

Codecov Report

Merging #135 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff          @@
##           master   #135   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files          20     20           
  Lines         791    796    +5     
  Branches       78     79    +1     
=====================================
+ Hits          791    796    +5
Impacted Files Coverage Δ
procrastinate/retry.py 100% <100%> (ø) ⬆️
procrastinate/worker.py 100% <100%> (ø) ⬆️
procrastinate/tasks.py 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b18f978...3256d4c. Read the comment docs.

Copy link
Contributor

@pmourlanne pmourlanne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of comments here and there (you know me 🙃 ) but code looks really good 👍

docs/howto/retry.rst Outdated Show resolved Hide resolved
docs/howto/retry.rst Outdated Show resolved Hide resolved
procrastinate/retry.py Outdated Show resolved Hide resolved
@ewjoachim
Copy link
Member Author

@pmourlanne both problems fixed

@ewjoachim
Copy link
Member Author

We could merge but @elemoine said he wanted to make a review, so let's wait until Monday/Tuesday.

Copy link
Contributor

@CorBott CorBott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To improve consistency, I'd stick to one way of expressing retry:
if you don't, jobs will be retried indefinitely until they pass
if you don't, jobs will be retried immediately
if you don't, jobs will be retried on any type of exceptions

@@ -17,15 +17,19 @@ class BaseRetryStrategy:
Children classes only need to implement `get_schedule_in`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: s/Children/Child (while you're at it)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't children the proper form as classes is plural? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah maybe not, as child is an adjective here :) .

@app.task(retry=procrastinate.RetryStrategy(
max_attempts=10,
wait=5,
retry_exceptions=[ConnectionError, IOError]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd use a tuple here instead of a list. To advertise better practices to our users.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what way is this a better practice to use a tuple here ? This is an array of homogeneous elements with arbitrary length, which fits better as a list IMHO, contrary to a tuple which works best as a fixed-length iterable where each element's type and signification is described through their position, no ?

Copy link
Member Author

@ewjoachim ewjoachim Feb 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be more precise, my rule of thumb:

  • If you have very specific performance constraints, you may explore the collections zoo (deque, ...)
  • If it makes no sense to have duplicates and order doesn't matter, it's a set
  • Else if any 2 elements could be swapped and it would still make sense, it's a list
  • Else if it can be used as basis for a namedtuple, it's a tuple (and you should consider using a namedtuple)
  • Else... I'm interested to know what iterable you've found that fail all of the above tests.

Copy link
Contributor

@elemoine elemoine Feb 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not go that far :-)

I just think a fixed-length, immutable, data structure makes more sense in such cases. In the same way isinstance receives a tuple as the second argument. Or when you write elem in ("foo", "bar").

But I don't mean to be too pedantic. Using a list is fine too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha sorry for being pedantic too :D

I think the fact ìsinstance() takes a tuple and not an iterable is an error from Python's youth.

Also, I think you were totally right questioning my choice of using a list: from my own rationale just above, a set would actually be much more appropriate (order doesn't matter and duplicates make no sense) 😆

And finally, regarding elem in ("foo", "bar"), I was curious if the most "appropriate" structure (here, a set) was also the most performant and it kinda looks like it is (with huge question marks regarding the validity of my benchmark):

In [1]: %timeit "baz" in {"foo", "bar"}
29.6 ns ± 0.79 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [2]: %timeit "baz" in ("foo", "bar")
57 ns ± 0.656 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [3]: %timeit "baz" in ["foo", "bar"]
58 ns ± 1.9 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

(this holds true if we're looking for the 2nd element but the 3 are as long if we're looking for the 1st element)
(Just to be clear, I'm not advocating for using one or another way just to earn a few nanoseconds as long as it's not on the critical path)

Copy link
Contributor

@elemoine elemoine left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two minor comments, otherwise looks very good to me!

@ewjoachim ewjoachim changed the title Retry exception 84 Retry on specific exception type 84 Feb 8, 2020
@ewjoachim ewjoachim requested a review from DainDwarf as a code owner February 8, 2020 12:52
@elemoine
Copy link
Contributor

@ewjoachim feel free to merge this whenever you think this is good to go.

@ewjoachim
Copy link
Member Author

Yes, just waiting for @CorBott to approve :)

Copy link
Contributor

@CorBott CorBott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine, thank you!

@ewjoachim ewjoachim merged commit 61396c7 into master Feb 10, 2020
@ewjoachim ewjoachim deleted the retry-exception-84 branch February 10, 2020 12:36
@ewjoachim ewjoachim mentioned this pull request Feb 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Retry depending on the exception
6 participants