Skip to content

Commit

Permalink
Merge pull request rholder#40 from cyrusd/master
Browse files Browse the repository at this point in the history
Callbacks for before/after attempts
  • Loading branch information
rholder committed Jun 6, 2016
2 parents 37b3222 + 6311fd3 commit 855db16
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 3 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.idea
dist
*.pyc
*.egg-info
*.egg-info
build
3 changes: 2 additions & 1 deletion AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ Patches and Suggestions
- Monty Taylor
- Maxym Shalenyi
- Jonathan Herriott
- Job Evers
- Job Evers
- Cyrus Durgin
12 changes: 11 additions & 1 deletion retrying.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ def __init__(self,
wrap_exception=False,
stop_func=None,
wait_func=None,
wait_jitter_max=None):
wait_jitter_max=None,
before_attempts=None,
after_attempts=None):

self._stop_max_attempt_number = 5 if stop_max_attempt_number is None else stop_max_attempt_number
self._stop_max_delay = 100 if stop_max_delay is None else stop_max_delay
Expand All @@ -82,6 +84,8 @@ def __init__(self,
self._wait_exponential_max = MAX_WAIT if wait_exponential_max is None else wait_exponential_max
self._wait_incrementing_max = MAX_WAIT if wait_incrementing_max is None else wait_incrementing_max
self._wait_jitter_max = 0 if wait_jitter_max is None else wait_jitter_max
self._before_attempts = before_attempts
self._after_attempts = after_attempts

# TODO add chaining of stop behaviors
# stop behavior
Expand Down Expand Up @@ -203,6 +207,9 @@ def call(self, fn, *args, **kwargs):
start_time = int(round(time.time() * 1000))
attempt_number = 1
while True:
if self._before_attempts:
self._before_attempts(attempt_number)

try:
attempt = Attempt(fn(*args, **kwargs), attempt_number, False)
except:
Expand All @@ -212,6 +219,9 @@ def call(self, fn, *args, **kwargs):
if not self.should_reject(attempt):
return attempt.get(self._wrap_exception)

if self._after_attempts:
self._after_attempts(attempt_number)

delay_since_first_attempt_ms = int(round(time.time() * 1000)) - start_time
if self.stop(attempt_number, delay_since_first_attempt_ms):
if not self._wrap_exception and attempt.has_exception:
Expand Down
34 changes: 34 additions & 0 deletions test_retrying.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,5 +434,39 @@ def test_defaults(self):
self.assertTrue(_retryable_default(NoCustomErrorAfterCount(5)))
self.assertTrue(_retryable_default_f(NoCustomErrorAfterCount(5)))

class TestBeforeAfterAttempts(unittest.TestCase):
_attempt_number = 0

def test_before_attempts(self):
TestBeforeAfterAttempts._attempt_number = 0

def _before(attempt_number):
TestBeforeAfterAttempts._attempt_number = attempt_number

@retry(wait_fixed = 1000, stop_max_attempt_number = 1, before_attempts = _before)
def _test_before():
pass

_test_before()

self.assertTrue(TestBeforeAfterAttempts._attempt_number is 1)

def test_after_attempts(self):
TestBeforeAfterAttempts._attempt_number = 0

def _after(attempt_number):
TestBeforeAfterAttempts._attempt_number = attempt_number

@retry(wait_fixed = 100, stop_max_attempt_number = 3, after_attempts = _after)
def _test_after():
if TestBeforeAfterAttempts._attempt_number < 2:
raise Exception("testing after_attempts handler")
else:
pass

_test_after()

self.assertTrue(TestBeforeAfterAttempts._attempt_number is 2)

if __name__ == '__main__':
unittest.main()

0 comments on commit 855db16

Please sign in to comment.